nordabiz/database/migrations/011_company_people.sql
Maciej Pienczyn abe1cd38a1 feat: Add PKD codes and CEIDG owner data to company profiles
- Add pkd_code, pkd_description columns for business activity classification
- Add business_start_date column from CEIDG
- Add owner_first_name, owner_last_name for JDG companies
- Create import script scripts/import_ceidg_to_db.py
- Add PKD card display in company profile template
- Add owner section for JDG companies without KRS
- Track SQL migrations in git (database/migrations/*.sql)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 16:07:03 +01:00

84 lines
3.5 KiB
SQL

-- Migration: Tabele dla osób powiązanych z firmami (zarząd, wspólnicy, prokurenci)
-- Data: 2026-01-11
-- Cel: Przechowywanie danych z odpisów KRS i budowanie mapy powiązań
-- Tabela osób (unikalna po PESEL lub kombinacji imię+nazwisko)
CREATE TABLE IF NOT EXISTS people (
id SERIAL PRIMARY KEY,
pesel VARCHAR(11) UNIQUE, -- może być NULL dla osób prawnych
imiona VARCHAR(255) NOT NULL,
nazwisko VARCHAR(255) NOT NULL,
-- Metadane
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
-- Constraint dla unikalności gdy brak PESEL
CONSTRAINT people_unique_name UNIQUE NULLS NOT DISTINCT (pesel, imiona, nazwisko)
);
-- Tabela powiązań osoba-firma
CREATE TABLE IF NOT EXISTS company_people (
id SERIAL PRIMARY KEY,
company_id INTEGER NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
person_id INTEGER NOT NULL REFERENCES people(id) ON DELETE CASCADE,
-- Rola w firmie
role VARCHAR(50) NOT NULL, -- PREZES ZARZĄDU, CZŁONEK ZARZĄDU, WSPÓLNIK, PROKURENT
role_category VARCHAR(20) NOT NULL, -- zarzad, wspolnik, prokurent
-- Dane dodatkowe (dla wspólników)
shares_count INTEGER, -- liczba udziałów
shares_value DECIMAL(12,2), -- wartość udziałów
shares_percent DECIMAL(5,2), -- procent udziałów
-- Źródło danych
source VARCHAR(100) DEFAULT 'ekrs.ms.gov.pl',
source_document VARCHAR(255), -- np. "odpis_pelny_0000725183.pdf"
fetched_at TIMESTAMP, -- kiedy pobrano dane
-- Metadane
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
-- Osoba może mieć tylko jedną rolę danej kategorii w firmie
CONSTRAINT company_people_unique UNIQUE (company_id, person_id, role_category, role)
);
-- Indeksy dla szybkiego wyszukiwania
CREATE INDEX IF NOT EXISTS idx_people_pesel ON people(pesel);
CREATE INDEX IF NOT EXISTS idx_people_nazwisko ON people(nazwisko);
CREATE INDEX IF NOT EXISTS idx_company_people_company ON company_people(company_id);
CREATE INDEX IF NOT EXISTS idx_company_people_person ON company_people(person_id);
CREATE INDEX IF NOT EXISTS idx_company_people_role ON company_people(role_category);
-- Widok dla łatwego wyszukiwania powiązań między firmami
CREATE OR REPLACE VIEW company_connections AS
SELECT
p.id as person_id,
p.imiona || ' ' || p.nazwisko as person_name,
p.pesel,
array_agg(DISTINCT c.name ORDER BY c.name) as companies,
array_agg(DISTINCT c.id ORDER BY c.id) as company_ids,
count(DISTINCT c.id) as company_count
FROM people p
JOIN company_people cp ON p.id = cp.person_id
JOIN companies c ON cp.company_id = c.id
GROUP BY p.id, p.imiona, p.nazwisko, p.pesel
HAVING count(DISTINCT c.id) > 1;
-- Uprawnienia dla aplikacji
GRANT ALL ON TABLE people TO nordabiz_app;
GRANT ALL ON TABLE company_people TO nordabiz_app;
GRANT USAGE, SELECT ON SEQUENCE people_id_seq TO nordabiz_app;
GRANT USAGE, SELECT ON SEQUENCE company_people_id_seq TO nordabiz_app;
GRANT SELECT ON company_connections TO nordabiz_app;
-- Komentarze
COMMENT ON TABLE people IS 'Osoby powiązane z firmami (zarząd, wspólnicy, prokurenci)';
COMMENT ON TABLE company_people IS 'Relacja wiele-do-wielu między osobami a firmami';
COMMENT ON VIEW company_connections IS 'Osoby powiązane z wieloma firmami Norda Biznes';
COMMENT ON COLUMN people.pesel IS 'PESEL osoby fizycznej (NULL dla osób prawnych)';
COMMENT ON COLUMN company_people.role IS 'Pełna nazwa funkcji np. PREZES ZARZĄDU';
COMMENT ON COLUMN company_people.role_category IS 'Kategoria: zarzad, wspolnik, prokurent';