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,181 @@
|
||||
# ANCOM — Registrul Furnizorilor de Comunicatii Electronice
|
||||
|
||||
**Status:** ingest implementat și aplicat (2026-05-10).
|
||||
**Sursă:** ANCOM (Autoritatea Națională pentru Administrare și Reglementare în Comunicații)
|
||||
**Lege:** Legea 159/2010 (registru public, transparență)
|
||||
|
||||
## Surse
|
||||
|
||||
URL listă autorizați (server-rendered HTML, paginat 10/pag, ~57 pag → ~570 furnizori):
|
||||
|
||||
```
|
||||
https://www.ancom.ro/reglementare-ro/comunicatii-electronice/
|
||||
furnizori-comunicatii-electronice/
|
||||
lista-furnizorilor-de-retele-si-servicii-de-comunicatii-autorizati/
|
||||
```
|
||||
|
||||
Pagination: POST `paged=N` (form `id="ms_form"`).
|
||||
|
||||
URL detaliu (per furnizor, `ancom_id` din lista):
|
||||
|
||||
```
|
||||
https://www.ancom.ro/sablon/furnizorinew_23/?id={ancom_id}&pid=4186
|
||||
```
|
||||
|
||||
Pagina de detaliu conține: Denumire, Adresa/Oras/Judet, **CUI direct** (Cod unic de
|
||||
înregistrare), EUID (Registrul Comerțului), tipuri de retele R1..R11 + servicii
|
||||
S1..S12 cu data nasterii dreptului.
|
||||
|
||||
## Schema SQL
|
||||
|
||||
Fișier: `services/seap-scraper/sql/029_ancom.sql`
|
||||
|
||||
3 tabele + 1 MV:
|
||||
- `ancom.operatori` — flat, PK `ancom_id` (din URL `?id=N`); CUI direct (no fuzzy)
|
||||
- `ancom.drepturi` — long table: 1 rând per (operator, R/S code) cu `data_nasterii`
|
||||
- `ancom.scrape_log` — mirror la convenția `anre.scrape_log`
|
||||
- `ancom.mv_operatori_per_cui` — rollup join cu `seap.announcements.supplier_cui`
|
||||
|
||||
## Fișiere
|
||||
|
||||
| Fișier | Linii | Rol |
|
||||
|---|---|---|
|
||||
| `sql/029_ancom.sql` | 113 | Schema (3 tabele + MV) |
|
||||
| `src/scrape-ancom.ts` | ~410 | Scraper TS (list paginate + detail HTML parser) |
|
||||
| `cron/scrape-ancom.sh` | 73 | Wrapper docker + Infisical Machine Identity |
|
||||
| `cron/match-cui-ancom.sh` | 175 | Stage A+B+C fallback pentru CUI lipsă |
|
||||
|
||||
## Pattern
|
||||
|
||||
Identic cu `scrape-anre.ts`:
|
||||
1. Infisical Machine Identity → env-file → `docker run --env-file` (NEVER `-e $VAR`)
|
||||
2. Idempotent (UPSERT pe `ancom_id`)
|
||||
3. CUI extras direct din pagina de detaliu (`<p><strong>Cod unic de înregistrare:</strong> N</p>`)
|
||||
4. `match-cui-ancom.sh` rulat **după** scrape pentru rândurile eventual rămase fără CUI
|
||||
|
||||
## Knobs
|
||||
|
||||
```bash
|
||||
# Smoke (1 pagină = 10 operatori)
|
||||
sudo MAX_PAGES=1 /opt/vreaudigital/services/seap-scraper/cron/scrape-ancom.sh
|
||||
|
||||
# Subset (limit primele N după dedup)
|
||||
sudo LIMIT=50 /opt/vreaudigital/services/seap-scraper/cron/scrape-ancom.sh
|
||||
|
||||
# Full
|
||||
sudo /opt/vreaudigital/services/seap-scraper/cron/scrape-ancom.sh
|
||||
|
||||
# CUI matcher (idempotent, doar NULL-urile)
|
||||
sudo /opt/vreaudigital/services/seap-scraper/cron/match-cui-ancom.sh
|
||||
```
|
||||
|
||||
## Cross-source recipes — DRAFT
|
||||
|
||||
### R1: Furnizori telco SEAP fără autorizație ANCOM (red flag)
|
||||
|
||||
Furnizori care au câștigat contracte SEAP cu CPV-uri telco (32xx — telecomm
|
||||
equipment, 64xx — postal & telecom services) dar **NU sunt** în registrul ANCOM
|
||||
de furnizori autorizați. Caz potențial: subcontractare, revânzare, sau activitate
|
||||
care necesită licență dar n-a fost solicitată.
|
||||
|
||||
```sql
|
||||
-- Furnizori SEAP cu contracte telco pe ultimii 24 luni dar absent ANCOM
|
||||
WITH telco_seap AS (
|
||||
SELECT
|
||||
a.supplier_cui,
|
||||
a.supplier_name,
|
||||
COUNT(*) AS nr_contracte,
|
||||
SUM(a.value_ron) AS valoare_totala_ron,
|
||||
array_agg(DISTINCT a.cpv_code) FILTER (WHERE a.cpv_code IS NOT NULL) AS cpv_codes
|
||||
FROM seap.announcements a
|
||||
WHERE a.supplier_cui IS NOT NULL
|
||||
AND a.publication_date >= now() - interval '24 months'
|
||||
AND (
|
||||
a.cpv_code LIKE '32%' OR -- echipamente telco
|
||||
a.cpv_code LIKE '64%' OR -- servicii postale & telecom
|
||||
a.cpv_code LIKE '72400%' -- internet services
|
||||
)
|
||||
GROUP BY a.supplier_cui, a.supplier_name
|
||||
)
|
||||
SELECT
|
||||
t.supplier_cui,
|
||||
t.supplier_name,
|
||||
t.nr_contracte,
|
||||
t.valoare_totala_ron,
|
||||
t.cpv_codes,
|
||||
-- profil firmă (caen + judet) pentru context
|
||||
e.caen_principal,
|
||||
e.adr_judet
|
||||
FROM telco_seap t
|
||||
LEFT JOIN ancom.mv_operatori_per_cui m ON m.cui = t.supplier_cui
|
||||
LEFT JOIN firms.entities e ON e.cui = t.supplier_cui
|
||||
WHERE m.cui IS NULL -- ! NU are autorizatie ANCOM
|
||||
AND t.valoare_totala_ron > 100000 -- relevant business volume
|
||||
ORDER BY t.valoare_totala_ron DESC
|
||||
LIMIT 100;
|
||||
```
|
||||
|
||||
### R2: Furnizori ANCOM autorizați — câți au câștigat contracte publice?
|
||||
|
||||
Inversul lui R1. Câți operatori autorizați ANCOM au cel puțin un contract SEAP?
|
||||
Care e concentrarea pe top 10?
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
m.cui,
|
||||
m.nr_autorizatii,
|
||||
m.retele,
|
||||
m.servicii,
|
||||
o_first.titular_name,
|
||||
COUNT(a.id) AS nr_contracte_seap,
|
||||
SUM(a.value_ron) AS valoare_seap_ron,
|
||||
MIN(a.publication_date) AS prima_castiga,
|
||||
MAX(a.publication_date) AS ultima_castiga
|
||||
FROM ancom.mv_operatori_per_cui m
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT titular_name FROM ancom.operatori WHERE titular_cui = m.cui LIMIT 1
|
||||
) o_first ON TRUE
|
||||
LEFT JOIN seap.announcements a ON a.supplier_cui = m.cui
|
||||
GROUP BY 1,2,3,4,5
|
||||
ORDER BY valoare_seap_ron DESC NULLS LAST
|
||||
LIMIT 50;
|
||||
```
|
||||
|
||||
### R3: Concentrare pe județe pentru drept S2 (mobil) sau R3 (fibră)
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
o.judet,
|
||||
COUNT(*) FILTER (WHERE d.cod = 'S2') AS nr_mobil,
|
||||
COUNT(*) FILTER (WHERE d.cod = 'R3') AS nr_fibra,
|
||||
COUNT(*) FILTER (WHERE d.cod = 'S1') AS nr_internet_fix,
|
||||
COUNT(DISTINCT o.titular_cui) AS nr_furnizori_unici
|
||||
FROM ancom.operatori o
|
||||
JOIN ancom.drepturi d ON d.ancom_id = o.ancom_id
|
||||
WHERE o.status = 'autorizat'
|
||||
GROUP BY 1
|
||||
ORDER BY nr_furnizori_unici DESC NULLS LAST
|
||||
LIMIT 25;
|
||||
```
|
||||
|
||||
## Limitări cunoscute
|
||||
|
||||
- Doar lista **autorizați** este ingest-ată. ANCOM mai publică:
|
||||
- lista furnizorilor radiați
|
||||
- lista furnizorilor sancționați (suspendare drepturi)
|
||||
- lista celor în libertate de prestare (cross-border)
|
||||
Toate folosesc același pattern `?pid={X}` și pot fi adăugate ca surse extra
|
||||
cu `status='radiat'`/`'sanctionat'`/`'cross-border'`.
|
||||
- `data_nasterii` per drept e data inițială — ANCOM nu publică data revocării
|
||||
per-drept, doar pe statusul global al furnizorului.
|
||||
- ~570 operatori / scrape ~3 min cu sleep 150ms per detail. Rulare lunară e suficientă;
|
||||
date public oarecum statice.
|
||||
|
||||
## Next steps
|
||||
|
||||
1. ~~Ingest autorizați~~ ✓ DONE
|
||||
2. Adaugă scrape-ancom-radiati.ts (sursa: lista furnizorilor radiați, pid=4318 sau similar)
|
||||
3. Crează recipe cross-source `furnizori_telco_neautorizati` în
|
||||
`src/lib/recipes.ts` (NU eu — exclusion zone) — pattern listat la R1 mai sus
|
||||
4. Pagină profil pe `/registru/ancom/[cui]` (similar cu beneficiar-privat) — NU eu
|
||||
5. CUI matcher cron lunar — adaugă în refresh-mvs.sh sau systemd timer dedicat
|
||||
Reference in New Issue
Block a user