a6c03a091e
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)
122 lines
4.7 KiB
PL/PgSQL
122 lines
4.7 KiB
PL/PgSQL
-- Materialized views for hub UI — refreshed nightly after WSP sync.
|
|
-- Provides fast aggregations for "Achiziții România live" dashboards.
|
|
BEGIN;
|
|
|
|
-- ── Daily totals: count + value per day (across all WSP sources) ──
|
|
CREATE MATERIALIZED VIEW IF NOT EXISTS seap.mv_daily_totals AS
|
|
SELECT
|
|
date_trunc('day', publication_date)::date AS day,
|
|
type,
|
|
count(*) AS notices,
|
|
sum(awarded_value) FILTER (WHERE awarded_value IS NOT NULL) AS total_awarded,
|
|
sum(estimated_value) FILTER (WHERE estimated_value IS NOT NULL) AS total_estimated,
|
|
count(DISTINCT authority_cui) AS distinct_authorities,
|
|
count(DISTINCT supplier_cui) AS distinct_suppliers
|
|
FROM seap.announcements
|
|
WHERE source LIKE 'wsp_%'
|
|
AND publication_date >= now() - interval '24 months'
|
|
GROUP BY 1, 2;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_mv_daily_totals_day ON seap.mv_daily_totals(day DESC);
|
|
|
|
|
|
-- ── Top contracting authorities (last 12 months by total awarded value) ──
|
|
CREATE MATERIALIZED VIEW IF NOT EXISTS seap.mv_top_authorities AS
|
|
SELECT
|
|
authority_cui,
|
|
authority_name,
|
|
county_code,
|
|
count(*) AS notices_count,
|
|
count(*) FILTER (WHERE type = 'ca_notice') AS awarded_count,
|
|
sum(awarded_value) FILTER (WHERE awarded_value IS NOT NULL) AS total_awarded,
|
|
avg(awarded_value) FILTER (WHERE awarded_value IS NOT NULL) AS avg_awarded,
|
|
array_agg(DISTINCT cpv_code) FILTER (WHERE cpv_code IS NOT NULL) AS cpv_codes,
|
|
max(publication_date) AS most_recent
|
|
FROM seap.announcements
|
|
WHERE source LIKE 'wsp_%'
|
|
AND authority_cui IS NOT NULL
|
|
AND publication_date >= now() - interval '12 months'
|
|
GROUP BY 1, 2, 3
|
|
HAVING count(*) >= 1;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_mv_top_auth_value ON seap.mv_top_authorities(total_awarded DESC NULLS LAST);
|
|
CREATE INDEX IF NOT EXISTS idx_mv_top_auth_cui ON seap.mv_top_authorities(authority_cui);
|
|
CREATE INDEX IF NOT EXISTS idx_mv_top_auth_county ON seap.mv_top_authorities(county_code);
|
|
|
|
|
|
-- ── Top suppliers (firms that won contracts) ──
|
|
CREATE MATERIALIZED VIEW IF NOT EXISTS seap.mv_top_suppliers AS
|
|
SELECT
|
|
supplier_cui,
|
|
supplier_name,
|
|
count(*) AS contracts_won,
|
|
sum(awarded_value) FILTER (WHERE awarded_value IS NOT NULL) AS total_awarded,
|
|
avg(awarded_value) FILTER (WHERE awarded_value IS NOT NULL) AS avg_awarded,
|
|
count(DISTINCT authority_cui) AS distinct_clients,
|
|
array_agg(DISTINCT cpv_code) FILTER (WHERE cpv_code IS NOT NULL) AS cpv_codes,
|
|
max(publication_date) AS most_recent
|
|
FROM seap.announcements
|
|
WHERE source LIKE 'wsp_%'
|
|
AND supplier_cui IS NOT NULL
|
|
AND type = 'ca_notice'
|
|
AND publication_date >= now() - interval '12 months'
|
|
GROUP BY 1, 2;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_mv_top_supp_value ON seap.mv_top_suppliers(total_awarded DESC NULLS LAST);
|
|
CREATE INDEX IF NOT EXISTS idx_mv_top_supp_cui ON seap.mv_top_suppliers(supplier_cui);
|
|
|
|
|
|
-- ── Top CPV codes (most-used categories) ──
|
|
CREATE MATERIALIZED VIEW IF NOT EXISTS seap.mv_top_cpv AS
|
|
SELECT
|
|
cpv_code,
|
|
count(*) AS notices_count,
|
|
sum(awarded_value) FILTER (WHERE awarded_value IS NOT NULL) AS total_awarded,
|
|
count(DISTINCT authority_cui) AS distinct_buyers,
|
|
count(DISTINCT supplier_cui) AS distinct_winners
|
|
FROM seap.announcements
|
|
WHERE source LIKE 'wsp_%'
|
|
AND cpv_code IS NOT NULL
|
|
AND publication_date >= now() - interval '12 months'
|
|
GROUP BY 1;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_mv_top_cpv_value ON seap.mv_top_cpv(total_awarded DESC NULLS LAST);
|
|
|
|
|
|
-- ── County totals (for map) ──
|
|
CREATE MATERIALIZED VIEW IF NOT EXISTS seap.mv_county_totals AS
|
|
SELECT
|
|
county_code,
|
|
type,
|
|
count(*) AS notices_count,
|
|
sum(awarded_value) FILTER (WHERE awarded_value IS NOT NULL) AS total_awarded
|
|
FROM seap.announcements
|
|
WHERE source LIKE 'wsp_%'
|
|
AND county_code IS NOT NULL
|
|
AND publication_date >= now() - interval '12 months'
|
|
GROUP BY 1, 2;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_mv_county_totals_code ON seap.mv_county_totals(county_code);
|
|
|
|
|
|
-- ── Refresh function (called by cron after daily sync) ──
|
|
CREATE OR REPLACE FUNCTION seap.refresh_wsp_views()
|
|
RETURNS void AS $$
|
|
BEGIN
|
|
REFRESH MATERIALIZED VIEW CONCURRENTLY seap.mv_daily_totals;
|
|
REFRESH MATERIALIZED VIEW CONCURRENTLY seap.mv_top_authorities;
|
|
REFRESH MATERIALIZED VIEW CONCURRENTLY seap.mv_top_suppliers;
|
|
REFRESH MATERIALIZED VIEW CONCURRENTLY seap.mv_top_cpv;
|
|
REFRESH MATERIALIZED VIEW CONCURRENTLY seap.mv_county_totals;
|
|
EXCEPTION WHEN feature_not_supported THEN
|
|
-- CONCURRENTLY requires unique index; first refresh is non-concurrent
|
|
REFRESH MATERIALIZED VIEW seap.mv_daily_totals;
|
|
REFRESH MATERIALIZED VIEW seap.mv_top_authorities;
|
|
REFRESH MATERIALIZED VIEW seap.mv_top_suppliers;
|
|
REFRESH MATERIALIZED VIEW seap.mv_top_cpv;
|
|
REFRESH MATERIALIZED VIEW seap.mv_county_totals;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
COMMIT;
|