initial: split from gov-agreg — vreau.digital standalone platform
Moved from gov-agreg/src/pages/achizitii/* to root (drop prefix). - 22 pages migrated, 127 files total - All internal links: /achizitii/X → /X (176 occurrences fixed) - AchizitiiLayout subnav rewritten: /X paths, top-right link to vreaudigital.ro hub - BaseLayout new (vreau.digital branding, OG tags, site URL) - astro.config.mjs: site https://vreau.digital, server output (was static) - docker-compose: port 5096 (vreaudigital is 5095), container vreau-digital - deploy.sh: paths /opt/vreau-digital, log /var/log/vreau-digital-deploy.log Backend shared with gov-agreg: - PostgreSQL satra (same schemas: seap, firms, anaf, anre, ...) - Photon, Martin tiles - Infisical /vreaudigital path (DATABASE_URL etc. shared) build: PASS (npx astro check 0 errors, npm run build 5s vite + 10s server)
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
-- SEAP Data Schema for Harta Banilor Publici
|
||||
-- Runs inside architools_db, isolated in schema "seap"
|
||||
-- ZERO modifications to existing public.* tables
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- Enable extensions needed for fuzzy matching
|
||||
CREATE EXTENSION IF NOT EXISTS pg_trgm;
|
||||
CREATE EXTENSION IF NOT EXISTS unaccent;
|
||||
|
||||
CREATE SCHEMA IF NOT EXISTS seap;
|
||||
|
||||
-- ── Entități SEAP (autorități contractante + furnizori) ──
|
||||
|
||||
CREATE TABLE seap.entities (
|
||||
entity_id INTEGER PRIMARY KEY,
|
||||
entity_type TEXT NOT NULL CHECK (entity_type IN ('authority', 'supplier')),
|
||||
fiscal_number TEXT,
|
||||
name TEXT NOT NULL,
|
||||
city TEXT,
|
||||
county TEXT,
|
||||
address TEXT,
|
||||
postal_code TEXT,
|
||||
is_utility BOOLEAN,
|
||||
siruta TEXT REFERENCES public."GisUat"(siruta),
|
||||
match_score REAL,
|
||||
fetched_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_entities_fiscal ON seap.entities(fiscal_number);
|
||||
CREATE INDEX idx_entities_siruta ON seap.entities(siruta);
|
||||
CREATE INDEX idx_entities_type ON seap.entities(entity_type);
|
||||
CREATE INDEX idx_entities_county ON seap.entities(county);
|
||||
|
||||
-- ── Achiziții directe ──
|
||||
|
||||
CREATE TABLE seap.direct_acquisitions (
|
||||
id INTEGER PRIMARY KEY,
|
||||
unique_code TEXT UNIQUE,
|
||||
name TEXT,
|
||||
cpv_code TEXT,
|
||||
cpv_name TEXT,
|
||||
publication_date TIMESTAMPTZ,
|
||||
finalization_date TIMESTAMPTZ,
|
||||
estimated_value NUMERIC(15,2),
|
||||
closing_value NUMERIC(15,2),
|
||||
currency TEXT DEFAULT 'RON',
|
||||
state_id INTEGER,
|
||||
state_text TEXT,
|
||||
contract_type_id INTEGER,
|
||||
contract_type_text TEXT,
|
||||
eu_fund_id INTEGER,
|
||||
eu_fund_text TEXT,
|
||||
authority_id INTEGER REFERENCES seap.entities(entity_id),
|
||||
supplier_id INTEGER REFERENCES seap.entities(entity_id),
|
||||
fetched_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_da_authority ON seap.direct_acquisitions(authority_id);
|
||||
CREATE INDEX idx_da_supplier ON seap.direct_acquisitions(supplier_id);
|
||||
CREATE INDEX idx_da_finalization ON seap.direct_acquisitions(finalization_date);
|
||||
CREATE INDEX idx_da_publication ON seap.direct_acquisitions(publication_date);
|
||||
CREATE INDEX idx_da_cpv ON seap.direct_acquisitions(cpv_code);
|
||||
CREATE INDEX idx_da_value ON seap.direct_acquisitions(closing_value);
|
||||
|
||||
-- ── Licitații publice (contract award notices) ──
|
||||
|
||||
CREATE TABLE seap.public_notices (
|
||||
id INTEGER PRIMARY KEY,
|
||||
notice_no TEXT,
|
||||
contract_title TEXT,
|
||||
cpv_code TEXT,
|
||||
cpv_name TEXT,
|
||||
estimated_value NUMERIC(15,2),
|
||||
contract_value NUMERIC(15,2),
|
||||
currency TEXT DEFAULT 'RON',
|
||||
publication_date TIMESTAMPTZ,
|
||||
state_date TIMESTAMPTZ,
|
||||
procedure_type_id INTEGER,
|
||||
procedure_type_text TEXT,
|
||||
contract_type_id INTEGER,
|
||||
contract_type_text TEXT,
|
||||
notice_type_id INTEGER,
|
||||
state_id INTEGER,
|
||||
state_text TEXT,
|
||||
authority_id INTEGER REFERENCES seap.entities(entity_id),
|
||||
authority_city TEXT,
|
||||
authority_county TEXT,
|
||||
authority_siruta TEXT REFERENCES public."GisUat"(siruta),
|
||||
has_lots BOOLEAN DEFAULT false,
|
||||
fetched_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_pn_authority ON seap.public_notices(authority_id);
|
||||
CREATE INDEX idx_pn_date ON seap.public_notices(publication_date);
|
||||
CREATE INDEX idx_pn_siruta ON seap.public_notices(authority_siruta);
|
||||
CREATE INDEX idx_pn_cpv ON seap.public_notices(cpv_code);
|
||||
|
||||
-- ── Contracte câștigate (din section 5 a licitațiilor) ──
|
||||
|
||||
CREATE TABLE seap.notice_contracts (
|
||||
id SERIAL PRIMARY KEY,
|
||||
notice_id INTEGER REFERENCES seap.public_notices(id),
|
||||
lot_number INTEGER,
|
||||
lot_title TEXT,
|
||||
contract_value NUMERIC(15,2),
|
||||
currency TEXT DEFAULT 'RON',
|
||||
contract_date DATE,
|
||||
winner_id INTEGER REFERENCES seap.entities(entity_id),
|
||||
winner_name TEXT,
|
||||
winner_fiscal TEXT,
|
||||
winner_city TEXT,
|
||||
winner_county TEXT,
|
||||
winner_siruta TEXT REFERENCES public."GisUat"(siruta),
|
||||
num_offers INTEGER
|
||||
);
|
||||
|
||||
CREATE INDEX idx_nc_notice ON seap.notice_contracts(notice_id);
|
||||
CREATE INDEX idx_nc_winner ON seap.notice_contracts(winner_id);
|
||||
CREATE INDEX idx_nc_winner_siruta ON seap.notice_contracts(winner_siruta);
|
||||
|
||||
-- ── Matching localități SEAP → SIRUTA ──
|
||||
|
||||
CREATE TABLE seap.locality_map (
|
||||
seap_city TEXT NOT NULL,
|
||||
seap_county TEXT NOT NULL,
|
||||
siruta TEXT REFERENCES public."GisUat"(siruta),
|
||||
match_type TEXT,
|
||||
confidence REAL,
|
||||
PRIMARY KEY (seap_city, seap_county)
|
||||
);
|
||||
|
||||
-- ── Stare sync scraper ──
|
||||
|
||||
CREATE TABLE seap.sync_state (
|
||||
source TEXT PRIMARY KEY,
|
||||
last_date TIMESTAMPTZ,
|
||||
last_id INTEGER,
|
||||
status TEXT,
|
||||
updated_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
INSERT INTO seap.sync_state (source, status) VALUES
|
||||
('da', 'pending'),
|
||||
('notices', 'pending');
|
||||
|
||||
-- ── Helper: normalize locality names ──
|
||||
|
||||
CREATE OR REPLACE FUNCTION seap.normalize_locality(input TEXT)
|
||||
RETURNS TEXT LANGUAGE sql IMMUTABLE AS $$
|
||||
SELECT lower(trim(unaccent(
|
||||
regexp_replace(input, '\s+', ' ', 'g')
|
||||
)));
|
||||
$$;
|
||||
|
||||
-- ── Materialized view: procurement stats per UAT ──
|
||||
|
||||
CREATE MATERIALIZED VIEW seap.uat_procurement_stats AS
|
||||
SELECT
|
||||
u.siruta,
|
||||
u.name AS uat_name,
|
||||
u.county,
|
||||
COALESCE(da_stats.da_count, 0) AS da_count,
|
||||
COALESCE(da_stats.da_total_value, 0) AS da_total_value,
|
||||
COALESCE(pn_stats.notice_count, 0) AS notice_count,
|
||||
COALESCE(pn_stats.notice_total_value, 0) AS notice_total_value,
|
||||
COALESCE(da_stats.da_count, 0) + COALESCE(pn_stats.notice_count, 0) AS total_contracts,
|
||||
COALESCE(da_stats.da_total_value, 0) + COALESCE(pn_stats.notice_total_value, 0) AS total_value
|
||||
FROM public."GisUat" u
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT
|
||||
COUNT(*) AS da_count,
|
||||
SUM(da.closing_value) AS da_total_value
|
||||
FROM seap.direct_acquisitions da
|
||||
JOIN seap.entities e ON e.entity_id = da.authority_id
|
||||
WHERE e.siruta = u.siruta
|
||||
) da_stats ON true
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT
|
||||
COUNT(*) AS notice_count,
|
||||
SUM(pn.contract_value) AS notice_total_value
|
||||
FROM seap.public_notices pn
|
||||
WHERE pn.authority_siruta = u.siruta
|
||||
) pn_stats ON true;
|
||||
|
||||
CREATE UNIQUE INDEX idx_ups_siruta ON seap.uat_procurement_stats(siruta);
|
||||
|
||||
COMMIT;
|
||||
Reference in New Issue
Block a user