- Model Announcement z kategoriami, statusami, slugami URL - Panel admina /admin/announcements (CRUD, filtry, AJAX) - Strona /ogloszenia tylko dla zalogowanych członków - Szczegóły ogłoszenia /ogloszenia/<slug> - Migracja SQL rozszerzająca istniejącą tabelę - Testowe ogłoszenia: ARP baza noclegowa, Tytani Przedsiębiorczości - Pliki PDF regulaminu i harmonogramu konkursu Tytani Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
178 lines
6.1 KiB
SQL
178 lines
6.1 KiB
SQL
-- ============================================================
|
|
-- Migration: 018_announcements.sql
|
|
-- Description: Rozszerzenie tabeli ogłoszeń o nowe pola
|
|
-- Author: Claude
|
|
-- Date: 2026-01-26
|
|
-- Note: Tabela announcements już istnieje - rozszerzamy ją
|
|
-- ============================================================
|
|
|
|
-- Dodanie nowych kolumn (jeśli nie istnieją)
|
|
-- slug: URL-friendly identyfikator
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'announcements' AND column_name = 'slug') THEN
|
|
ALTER TABLE announcements ADD COLUMN slug VARCHAR(300);
|
|
END IF;
|
|
END $$;
|
|
|
|
-- excerpt: Krótki opis do listy
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'announcements' AND column_name = 'excerpt') THEN
|
|
ALTER TABLE announcements ADD COLUMN excerpt VARCHAR(500);
|
|
END IF;
|
|
END $$;
|
|
|
|
-- category: Nowa kategoryzacja (general, event, opportunity, member_news, partnership)
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'announcements' AND column_name = 'category') THEN
|
|
ALTER TABLE announcements ADD COLUMN category VARCHAR(50) DEFAULT 'general';
|
|
END IF;
|
|
END $$;
|
|
|
|
-- image_url: Obrazek ogłoszenia
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'announcements' AND column_name = 'image_url') THEN
|
|
ALTER TABLE announcements ADD COLUMN image_url VARCHAR(1000);
|
|
END IF;
|
|
END $$;
|
|
|
|
-- external_link: Link do zewnętrznego źródła
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'announcements' AND column_name = 'external_link') THEN
|
|
ALTER TABLE announcements ADD COLUMN external_link VARCHAR(1000);
|
|
END IF;
|
|
END $$;
|
|
|
|
-- status: draft, published, archived (zastępuje is_published)
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'announcements' AND column_name = 'status') THEN
|
|
ALTER TABLE announcements ADD COLUMN status VARCHAR(20) DEFAULT 'draft';
|
|
END IF;
|
|
END $$;
|
|
|
|
-- published_at: Data publikacji
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'announcements' AND column_name = 'published_at') THEN
|
|
ALTER TABLE announcements ADD COLUMN published_at TIMESTAMP;
|
|
END IF;
|
|
END $$;
|
|
|
|
-- expires_at: Data wygaśnięcia (zastępuje expire_date)
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'announcements' AND column_name = 'expires_at') THEN
|
|
ALTER TABLE announcements ADD COLUMN expires_at TIMESTAMP;
|
|
END IF;
|
|
END $$;
|
|
|
|
-- is_featured: Wyróżnienie
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'announcements' AND column_name = 'is_featured') THEN
|
|
ALTER TABLE announcements ADD COLUMN is_featured BOOLEAN DEFAULT FALSE;
|
|
END IF;
|
|
END $$;
|
|
|
|
-- views_count: Licznik wyświetleń
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'announcements' AND column_name = 'views_count') THEN
|
|
ALTER TABLE announcements ADD COLUMN views_count INTEGER DEFAULT 0;
|
|
END IF;
|
|
END $$;
|
|
|
|
-- created_by: ID użytkownika (mapowanie z author_id)
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
WHERE table_name = 'announcements' AND column_name = 'created_by') THEN
|
|
ALTER TABLE announcements ADD COLUMN created_by INTEGER REFERENCES users(id) ON DELETE SET NULL;
|
|
END IF;
|
|
END $$;
|
|
|
|
-- Migracja danych ze starych kolumn do nowych
|
|
-- Mapowanie announcement_type -> category
|
|
UPDATE announcements
|
|
SET category = CASE
|
|
WHEN announcement_type = 'fees' THEN 'general'
|
|
WHEN announcement_type = 'important' THEN 'general'
|
|
WHEN announcement_type = 'urgent' THEN 'general'
|
|
WHEN announcement_type = 'event' THEN 'event'
|
|
ELSE COALESCE(announcement_type, 'general')
|
|
END
|
|
WHERE category IS NULL OR category = '';
|
|
|
|
-- Mapowanie is_published -> status
|
|
UPDATE announcements
|
|
SET status = CASE
|
|
WHEN is_published = true THEN 'published'
|
|
ELSE 'draft'
|
|
END
|
|
WHERE status IS NULL OR status = '';
|
|
|
|
-- Mapowanie expire_date -> expires_at
|
|
UPDATE announcements
|
|
SET expires_at = expire_date
|
|
WHERE expires_at IS NULL AND expire_date IS NOT NULL;
|
|
|
|
-- Mapowanie publish_date -> published_at
|
|
UPDATE announcements
|
|
SET published_at = COALESCE(publish_date, created_at)
|
|
WHERE published_at IS NULL AND is_published = true;
|
|
|
|
-- Mapowanie author_id -> created_by
|
|
UPDATE announcements
|
|
SET created_by = author_id
|
|
WHERE created_by IS NULL AND author_id IS NOT NULL;
|
|
|
|
-- Generowanie slugów dla istniejących ogłoszeń
|
|
UPDATE announcements
|
|
SET slug = CONCAT(
|
|
LOWER(REGEXP_REPLACE(
|
|
REGEXP_REPLACE(title, '[^a-zA-Z0-9\s]', '', 'g'),
|
|
'\s+', '-', 'g'
|
|
)),
|
|
'-', id
|
|
)
|
|
WHERE slug IS NULL OR slug = '';
|
|
|
|
-- Tworzenie indeksów (jeśli nie istnieją)
|
|
CREATE INDEX IF NOT EXISTS idx_announcements_status ON announcements(status);
|
|
CREATE INDEX IF NOT EXISTS idx_announcements_slug ON announcements(slug);
|
|
CREATE INDEX IF NOT EXISTS idx_announcements_published_at ON announcements(published_at DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_announcements_category ON announcements(category);
|
|
|
|
-- Tworzenie unikalności na slug
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE indexname = 'idx_announcements_slug_unique') THEN
|
|
CREATE UNIQUE INDEX idx_announcements_slug_unique ON announcements(slug) WHERE slug IS NOT NULL;
|
|
END IF;
|
|
END $$;
|
|
|
|
-- Uprawnienia
|
|
GRANT ALL ON TABLE announcements TO nordabiz_app;
|
|
GRANT USAGE, SELECT ON SEQUENCE announcements_id_seq TO nordabiz_app;
|
|
|
|
-- Komentarze
|
|
COMMENT ON COLUMN announcements.slug IS 'URL-friendly slug (np. baza-noclegowa-arp-choczewo)';
|
|
COMMENT ON COLUMN announcements.excerpt IS 'Krótki opis do listy (max 500 znaków)';
|
|
COMMENT ON COLUMN announcements.category IS 'Kategoria: general, event, opportunity, member_news, partnership';
|
|
COMMENT ON COLUMN announcements.status IS 'Status: draft, published, archived';
|