-- ============================================================ -- NordaBiz - Migration 003: Membership Fees Management -- ============================================================ -- Created: 2026-01-04 -- Description: -- - Creates membership_fees table for tracking monthly payments -- - Creates membership_fee_config for fee amount configuration -- - Creates announcements table for board communications -- ============================================================ -- ============================================================ -- 1. MEMBERSHIP FEES TABLE -- ============================================================ CREATE TABLE IF NOT EXISTS membership_fees ( id SERIAL PRIMARY KEY, company_id INTEGER NOT NULL REFERENCES companies(id) ON DELETE CASCADE, -- Period fee_year INTEGER NOT NULL, fee_month INTEGER NOT NULL CHECK (fee_month >= 1 AND fee_month <= 12), -- Amounts amount NUMERIC(10, 2) NOT NULL, amount_paid NUMERIC(10, 2) DEFAULT 0, -- Status: pending, paid, partial, overdue, waived status VARCHAR(20) DEFAULT 'pending', -- Payment details payment_date DATE, payment_method VARCHAR(50), payment_reference VARCHAR(100), -- Admin tracking recorded_by INTEGER REFERENCES users(id), recorded_at TIMESTAMP, notes TEXT, -- Timestamps created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW(), -- Unique constraint: one fee record per company per month CONSTRAINT uq_company_fee_period UNIQUE (company_id, fee_year, fee_month) ); CREATE INDEX IF NOT EXISTS idx_membership_fees_company ON membership_fees(company_id); CREATE INDEX IF NOT EXISTS idx_membership_fees_period ON membership_fees(fee_year, fee_month); CREATE INDEX IF NOT EXISTS idx_membership_fees_status ON membership_fees(status); COMMENT ON TABLE membership_fees IS 'Monthly membership fee tracking for Norda Biznes companies'; -- ============================================================ -- 2. FEE CONFIGURATION TABLE -- ============================================================ CREATE TABLE IF NOT EXISTS membership_fee_config ( id SERIAL PRIMARY KEY, scope VARCHAR(20) NOT NULL, -- 'global', 'category', 'company' category_id INTEGER REFERENCES categories(id), company_id INTEGER REFERENCES companies(id), monthly_amount NUMERIC(10, 2) NOT NULL, valid_from DATE NOT NULL, valid_until DATE, created_by INTEGER REFERENCES users(id), created_at TIMESTAMP DEFAULT NOW(), notes TEXT ); CREATE INDEX IF NOT EXISTS idx_fee_config_scope ON membership_fee_config(scope); CREATE INDEX IF NOT EXISTS idx_fee_config_validity ON membership_fee_config(valid_from, valid_until); -- Insert default global fee (100 PLN) INSERT INTO membership_fee_config (scope, monthly_amount, valid_from, notes) VALUES ('global', 100.00, '2026-01-01', 'Domyslna skladka miesieczna') ON CONFLICT DO NOTHING; COMMENT ON TABLE membership_fee_config IS 'Configuration for membership fee amounts'; -- ============================================================ -- 3. ANNOUNCEMENTS TABLE -- ============================================================ CREATE TABLE IF NOT EXISTS announcements ( id SERIAL PRIMARY KEY, title VARCHAR(255) NOT NULL, content TEXT NOT NULL, -- Types: general, fees, event, important, urgent announcement_type VARCHAR(50) DEFAULT 'general', is_published BOOLEAN DEFAULT FALSE, is_pinned BOOLEAN DEFAULT FALSE, publish_date TIMESTAMP, expire_date TIMESTAMP, -- Target: all, fee_pending, fee_overdue target_audience VARCHAR(50) DEFAULT 'all', author_id INTEGER NOT NULL REFERENCES users(id), created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_announcements_published ON announcements(is_published); CREATE INDEX IF NOT EXISTS idx_announcements_type ON announcements(announcement_type); CREATE INDEX IF NOT EXISTS idx_announcements_dates ON announcements(publish_date, expire_date); COMMENT ON TABLE announcements IS 'Board announcements visible to logged-in members'; -- ============================================================ -- MIGRATION COMPLETE -- ============================================================