Skip to content

Add 2014-2020 EU structural-funds domain - #84

Merged
namedgraph merged 1 commit into
masterfrom
feat/eu-funds-domain
Oct 26, 2026
Merged

namedgraph merged 1 commit into
masterfrom
feat/eu-funds-domain

Conversation

@namedgraph

Copy link
Copy Markdown
Member

Stacked on #82 (base feat/insolvency-domain). Review/merge #82 first; GitHub will retarget this to master once #82 lands.

Summary

Third Tier 1 source. A new etl/eu-funds/ domain — one ltlod:EUFundingContract per 2014-2020 EU structural-funds implementation contract (finmin/sutartys/Contract, ~26k), joined to legal-entities/ by the bare JAR code so the beneficiary (executor_code) and project partners (ConPartner) link with no lookup. Opens the cases politicians' companies that received EU funds and companies with both EU funds and public contracts.

What the data actually is (verified, differs from the original plan)

  • Only ~685 of ~26k contracts carry a formal project code (03.3.1-…) via finmin/paraiskos/Project, with the EU / total / decided amounts and a ConFinSource breakdown. The rest are code-less financial-instrument payouts (e.g. partial interest compensation to SMEs) — beneficiary + dates + aid flags only. Per the maintainer's call, all ~26k are kept (maximises the "which companies got EU money" JAR coverage).
  • Repayments and irregularities are NOT modelled. sutartys/Repayment and kontroles_veiksmai/Suspicion are keyed by a project_hash / project_hash_id that is a hash of an unpublished internal SFMIS id. I tested the allowed hash-comparison bridge — every published id (project code, _id, project_id, Contract._id) under md5/sha*/crc/blake, salted and prefix/suffix — 0 matches, so repayments/irregularities can't be attributed to a project or beneficiary. The planned eu-irregularities-by-beneficiary case is therefore infeasible; eu-funds-and-procurement replaces it. The 2021-2027 programme is not on Spinta.

Model

  • ltlod:beneficiary / ltlod:fundingPartner → legal-entities/{code}/#this (each with its own inverse view); sdmx-dimension:refArea → the municipality; ltlod:euAmount / totalAmount / decidedEuAmount (EUR, coded ones); dct:date + dct:temporal → the start day; ltlod:implementationFrom/Till literals; ltlod:stateAid / deMinimisAid booleans; dct:identifier → the project code.
  • ltlod-eu-funds keyset-paginates Contract, joins ConPartner/ConFinSource by Contract._id and the project by Contract.project._id, and crosswalks the free-text municipality to the AR sav_kodas.

Verification (2026-10-25 finmin feeds)

  • 25,978 contracts (3 dropped with no beneficiary code), 685 coded, 1,820 partner links. All graphs validate, SHACL conforms, no blank nodes; 1,650 distinct start days and all 60 municipalities resolve, 0 dangling. Beneficiary/partner links into legal-entities/ dangle until the full JAR register is loaded — expected. Gitignored bulk output (~29 MB).
  • Both example queries return real rows end-to-end (e.g. a politician tied to a company with €2.7M EU funds; UAB Vilniaus kogeneracinė jėgainė with €138M EU + €6.6M procurement). EXAMPLES.md updated with the two sections only.

🤖 Generated with Claude Code

New etl/eu-funds/ domain: one ltlod:EUFundingContract per implementation contract
(finmin/sutartys/Contract, ~26k), joined to legal-entities/ by the bare JAR code so the
beneficiary (executor_code) and project partners (ConPartner) link with no lookup. ~685
carry a formal project code (via finmin/paraiskos/Project) with the EU / total / decided
amounts and a ConFinSource breakdown; the rest are code-less financial-instrument payouts
(e.g. partial interest compensation to SMEs) with the beneficiary, dates and aid flags only.

ltlod-eu-funds (registered uv tool) keyset-paginates Contract, joins ConPartner/ConFinSource
by Contract._id and paraiskos/Project by Contract.project._id, and crosswalks the free-text
municipality to the AR sav_kodas (normalising the abbreviation; a unique-stem fallback for
"Visagino miesto"). Contracts with no beneficiary code are dropped (3).

app/ns.ttl: ltlod:EUFundingContract + ltlod:beneficiary / ltlod:fundingPartner (each with its
inverse view on the legal entity) and the amount/flag/date properties; :DayEUFunding on
dct:temporal (a day's contract starts). app/eu-funds.ttl container with top-beneficiaries and
per-year charts (no children listing for 26k docs). SHACL shapes in etl/shapes/eu-funds.ttl.
contracts.trig is gitignored bulk output (~29 MB). Part of `make all`.

Two cross-domain cases joined on the JAR code: politicians' companies that received EU funds
(vtek × eu-funds), and companies with both EU funds and public contracts (eu-funds ×
procurement).

NOT modelled, documented as gaps: Repayment (lėšų grąžinimai) and kontroles_veiksmai/Suspicion
(pažeidimai) are keyed by a project_hash / project_hash_id that is a hash of an unpublished
internal SFMIS identifier — tested against every published id (code, _id, project_id,
Contract._id) under md5/sha*/crc/blake, salted and prefix/suffix, with no match, so repayments
and irregularities cannot be attributed to a beneficiary. The 2021-2027 programme is not on Spinta.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Base automatically changed from feat/insolvency-domain to master October 26, 2026 08:59
@namedgraph
namedgraph merged commit 4abbb77 into master Oct 26, 2026
4 checks passed
@namedgraph
namedgraph deleted the feat/eu-funds-domain branch October 26, 2026 09:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant