#!/usr/bin/env python3 """ Import danych z WhatsApp grupy Norda Biznes (4-11.02.2026) Zawiera: - Nowe wydarzenia: Szkolenie KSeF 23.02, Chwila dla Biznesu 26.02 (jeśli brak) - Update speaker info: Śniadanie 20.02 (ID=43) - Uzupełnienie opisów firm: Fiume Studio (128), PG Construction (49), Green House Systems (24) - Nowa firma: Alter Energy (child brand pod Fiume Studio) - UserCompany: Irmina (user 67) → Alter Energy - Ogłoszenie: Chorwacja pod Żaglami Użycie: python3 scripts/import_whatsapp_feb2026.py # dry-run python3 scripts/import_whatsapp_feb2026.py --apply # zapis do bazy """ import os import sys from pathlib import Path from datetime import date, time, datetime sys.path.insert(0, str(Path(__file__).parent.parent)) from sqlalchemy import create_engine, text from sqlalchemy.orm import sessionmaker def load_env(): """Załaduj .env z katalogu projektu.""" env_path = Path(__file__).parent.parent / '.env' if env_path.exists(): with open(env_path, 'r') as f: for line in f: line = line.strip() if line and not line.startswith('#') and '=' in line: key, value = line.split('=', 1) os.environ.setdefault(key.strip(), value.strip()) load_env() DATABASE_URL = os.getenv('DATABASE_URL', 'postgresql://nordabiz_app:CHANGE_ME@127.0.0.1:5432/nordabiz') SOURCE = 'whatsapp_norda_feb2026' def main(): dry_run = '--apply' not in sys.argv print("=" * 70) print("IMPORT: WhatsApp Norda Biznes (4-11.02.2026)") print(f"MODE: {'DRY-RUN (brak zapisu)' if dry_run else 'APPLY (zapis do bazy!)'}") print("=" * 70) engine = create_engine(DATABASE_URL) Session = sessionmaker(bind=engine) session = Session() stats = {'added': 0, 'updated': 0, 'skipped': 0} try: # ============================================================ # 1. WYDARZENIA # ============================================================ print("\n--- 1. WYDARZENIA ---\n") # 1a. Szkolenie KSeF 23.02 existing = session.execute( text("SELECT id FROM norda_events WHERE event_date = :d AND title ILIKE :t"), {"d": date(2026, 2, 23), "t": "%KSeF%"} ).fetchone() if existing: print(f" SKIP: Szkolenie KSeF 23.02 juz istnieje (ID={existing[0]})") stats['skipped'] += 1 else: print(" + ADD: Szkolenie KSeF 23.02") if not dry_run: session.execute(text(""" INSERT INTO norda_events (title, description, event_type, event_date, time_start, time_end, location, source, source_note, access_level, created_at) VALUES (:title, :desc, :etype, :edate, :tstart, :tend, :loc, :src, :src_note, :access, NOW()) """), { "title": "Szkolenie — Zmiany podatkowe i KSeF 2026", "desc": "Szkolenie z zakresu zmian podatkowych obowiazujacych od nowego roku oraz KSeF. " "Dostepne dla czlonkow Izby NORDA, ich pracownikow i osob prowadzacych rozliczenia ksiegowe. " "Firmy spoza Izby — koszt 250 zl/os. Kontakt: sekretariat Nordy (Magda).", "etype": "meeting", "edate": date(2026, 2, 23), "tstart": time(9, 0), "tend": time(14, 30), "loc": "Urzad Miejski Wejherowo, ul. 12 Marca, ostatnie pietro", "src": SOURCE, "src_note": "WhatsApp grupa Norda, Roman, 8.02.2026", "access": "members_only", }) stats['added'] += 1 # 1b. Chwila dla Biznesu 26.02 — sprawdz czy istnieje existing = session.execute( text("SELECT id FROM norda_events WHERE event_date = :d AND title ILIKE :t"), {"d": date(2026, 2, 26), "t": "%Chwila%"} ).fetchone() if existing: print(f" SKIP: Chwila dla Biznesu 26.02 juz istnieje (ID={existing[0]})") stats['skipped'] += 1 else: print(" + ADD: Chwila dla Biznesu 26.02") if not dry_run: session.execute(text(""" INSERT INTO norda_events (title, description, event_type, event_date, time_start, location, source, source_note, access_level, created_at) VALUES (:title, :desc, :etype, :edate, :tstart, :loc, :src, :src_note, :access, NOW()) """), { "title": "Chwila dla Biznesu — luty 2026", "desc": "Comiesięczne spotkanie networkingowe członków Izby NORDA.", "etype": "networking", "edate": date(2026, 2, 26), "tstart": time(19, 0), "loc": "Hotel Olimp, V piętro, Wejherowo", "src": SOURCE, "src_note": "WhatsApp grupa Norda, Roman, 11.02.2026", "access": "members_only", }) stats['added'] += 1 # 1c. Śniadanie 20.02 (ID=43) — UPDATE speaker info event43 = session.execute( text("SELECT id, speaker_name, speaker_company_id FROM norda_events WHERE id = 43") ).fetchone() if not event43: print(" WARN: Wydarzenie ID=43 nie istnieje!") elif event43[1] and event43[2]: print(f" SKIP: Sniadanie ID=43 ma juz speaker: {event43[1]} (company_id={event43[2]})") stats['skipped'] += 1 else: print(f" ~ UPD: Sniadanie ID=43 — speaker: Alicja Domachowska, company_id=40 (Lean Idea)") if not dry_run: session.execute(text(""" UPDATE norda_events SET speaker_name = :speaker, speaker_company_id = :cid WHERE id = 43 """), {"speaker": "Alicja Domachowska", "cid": 40}) stats['updated'] += 1 # ============================================================ # 2. UZUPEŁNIENIE OPISÓW FIRM # ============================================================ print("\n--- 2. UZUPELNIENIE OPISOW FIRM ---\n") company_updates = [ { "id": 128, "name": "Fiume Studio", "description_short": "Fiume Studio — atelier kulinarne i sala eventowa w Redzie. Warsztaty kulinarne, eventy firmowe, catering.", "services_offered": "Warsztaty kulinarne, sala bankietowa, eventy firmowe, warsztaty pizzy, catering", }, { "id": 49, "name": "PG Construction", "description_short": "Projektowanie, nadzór budowlany, kompleksowa obsługa inwestycji budowlanych, obsługa deweloperów.", "services_offered": "Projektowanie budowlane, nadzór budowlany, kompleksowa obsługa inwestycji budowlanych, obsługa deweloperów", }, { "id": 24, "name": "Green House Systems", "description_short": "Firma instalacyjna — wod-kan, ogrzewanie podłogowe, rekuperacja, klimatyzacja, instalacje elektryczne z automatyką budynkową, fotowoltaika z magazynem energii.", "services_offered": "Instalacje wod-kan, ogrzewanie podłogowe, rekuperacja, klimatyzacja, instalacje elektryczne, automatyka budynkowa, fotowoltaika, magazyny energii", "website": "https://www.greenhousesystems.pl", }, ] for cu in company_updates: row = session.execute( text("SELECT id, name, description_short, services_offered, website FROM companies WHERE id = :id"), {"id": cu["id"]} ).fetchone() if not row: print(f" WARN: Firma ID={cu['id']} ({cu['name']}) nie istnieje!") continue updates = [] params = {"id": cu["id"]} # description_short — update only if empty if not row[2] or row[2].strip() == '': updates.append("description_short = :desc_short") params["desc_short"] = cu["description_short"] else: print(f" SKIP: {cu['name']} (ID={cu['id']}) — description_short juz wypelnione") # services_offered — update only if empty if not row[3] or row[3].strip() == '': updates.append("services_offered = :services") params["services"] = cu["services_offered"] else: print(f" SKIP: {cu['name']} (ID={cu['id']}) — services_offered juz wypelnione") # website — update only if empty and provided if "website" in cu: if not row[4] or row[4].strip() == '': updates.append("website = :website") params["website"] = cu["website"] else: print(f" SKIP: {cu['name']} (ID={cu['id']}) — website juz wypelnione") if updates: set_clause = ", ".join(updates) print(f" ~ UPD: {cu['name']} (ID={cu['id']}) — {', '.join(u.split(' =')[0] for u in updates)}") if not dry_run: session.execute( text(f"UPDATE companies SET {set_clause}, last_updated = NOW() WHERE id = :id"), params ) stats['updated'] += 1 else: stats['skipped'] += 1 # ============================================================ # 3. NOWA FIRMA: Alter Energy # ============================================================ print("\n--- 3. NOWA FIRMA: Alter Energy ---\n") existing_alter = session.execute( text("SELECT id FROM companies WHERE slug = 'alter-energy'") ).fetchone() alter_energy_id = None if existing_alter: alter_energy_id = existing_alter[0] print(f" SKIP: Alter Energy juz istnieje (ID={alter_energy_id})") stats['skipped'] += 1 else: print(" + ADD: Alter Energy (child brand pod Fiume Studio, ID=128)") if not dry_run: result = session.execute(text(""" INSERT INTO companies (name, slug, phone, parent_company_id, status, data_quality, data_source, created_at, last_updated) VALUES (:name, :slug, :phone, :parent_id, :status, :dq, :ds, NOW(), NOW()) RETURNING id """), { "name": "Alter Energy", "slug": "alter-energy", "phone": "508259086", "parent_id": 128, "status": "active", "dq": "basic", "ds": SOURCE, }) alter_energy_id = result.fetchone()[0] print(f" → ID={alter_energy_id}") stats['added'] += 1 # 3b. UserCompany: Irmina (user 67) → Alter Energy if alter_energy_id: existing_uc = session.execute( text("SELECT id FROM user_companies WHERE user_id = 67 AND company_id = :cid"), {"cid": alter_energy_id} ).fetchone() if existing_uc: print(f" SKIP: UserCompany Irmina(67) → Alter Energy({alter_energy_id}) juz istnieje") stats['skipped'] += 1 else: print(f" + ADD: UserCompany Irmina(67) → Alter Energy({alter_energy_id}), role=MANAGER, is_primary=false") if not dry_run: session.execute(text(""" INSERT INTO user_companies (user_id, company_id, role, is_primary, created_at, updated_at) VALUES (67, :cid, 'MANAGER', false, NOW(), NOW()) """), {"cid": alter_energy_id}) stats['added'] += 1 else: if dry_run: print(" (dry-run) UserCompany Irmina → Alter Energy zostanie dodane przy --apply") # ============================================================ # 4. OGŁOSZENIE: Chorwacja pod Żaglami # ============================================================ print("\n--- 4. OGLOSZENIE: Chorwacja pod Zaglami ---\n") existing_ann = session.execute( text("SELECT id FROM announcements WHERE slug = 'chorwacja-pod-zaglami'") ).fetchone() if existing_ann: print(f" SKIP: Ogłoszenie 'Chorwacja pod Zaglami' juz istnieje (ID={existing_ann[0]})") stats['skipped'] += 1 else: # Find admin user for created_by admin_user = session.execute( text("SELECT id FROM users WHERE is_admin = true ORDER BY id LIMIT 1") ).fetchone() admin_id = admin_user[0] if admin_user else 1 print(" + ADD: Ogloszenie 'Chorwacja pod Zaglami'") if not dry_run: session.execute(text(""" INSERT INTO announcements (title, slug, excerpt, content, categories, status, published_at, created_by, created_at, updated_at) VALUES (:title, :slug, :excerpt, :content, :cats, 'published', NOW(), :created_by, NOW(), NOW()) """), { "title": "Chorwacja pod Żaglami — wyjazd integracyjny", "slug": "chorwacja-pod-zaglami", "excerpt": "Pomysł Prezesa Leszka Glazy — wspólny wyjazd pod żaglami do Chorwacji. Kontakt: sekretariat Nordy (Magda) lub Prezes.", "content": "

Zapraszamy na wyjazd integracyjny do Chorwacji pod żaglami! Pomysł naszego Prezesa Leszka Glazy.

" "

Poprzednie wspólne wyjazdy (USA, Hawaje) były wielkim sukcesem. " "Szczegóły do uzgodnienia — prosimy o kontakt z sekretariatem Nordy (Magda) lub bezpośrednio z Prezesem.

", "cats": ["event"], "created_by": admin_id, }) stats['added'] += 1 # ============================================================ # COMMIT # ============================================================ if not dry_run: session.commit() print("\n>>> COMMIT OK") # ============================================================ # PODSUMOWANIE # ============================================================ print("\n" + "=" * 70) print(f"PODSUMOWANIE: dodano={stats['added']}, zaktualizowano={stats['updated']}, pominieto={stats['skipped']}") if dry_run: print("[DRY-RUN] Zadne dane NIE zostaly zapisane. Uzyj --apply aby zapisac.") print("=" * 70) except Exception as e: session.rollback() print(f"\nBLAD: {e}") import traceback traceback.print_exc() sys.exit(1) finally: session.close() if __name__ == "__main__": main()