--- name: political-party-membership description: Retrieve current Estonian political-party and member lists from the e-Business Register, including direct CSV exports by registry code. module: erakonnad.mjs execution: code --- # Political Party Membership Party membership is public under the Political Parties Act, and the e-Business Register publishes each party's current member list as a CSV export. No authentication, no session cookie. ## Use when - You need how large a party is, or how the parties compare. - You need to check whether a named person is on a party's public list. - **Not** for campaign finance — that is `party-funding-data`. ## Retrieve **Use the module below.** It resolves the party, downloads the register's own CSV and counts in code. ```js const r = await partyMembership("Reformierakond"); show(r.totals); // { members, suspended, byJoinYear, joinedThisYear, longestServing } const all = await partyMembershipRanking(); // every registered party, one call show(all.totals); // { parties, members, largest } show(all.rows); // party, members, sharePct ``` `partyMembershipRanking()` downloads all 14 registered parties (~1.8 MB, ~6 s) and ranks them, so a "which party is biggest" question needs no second call and no hand-added subtotals. ## What `byJoinYear` is, and is not It counts **how many of today's members joined in each year**. It is *not* the party's membership in that year: everyone who has since left is absent, so the series slopes downward into the past for reasons that have nothing to do with recruitment. The register holds **no leave dates at all**. State what the series measures, or say nothing about the trend — this is the caveat the module's `note` repeats because it is the easiest wrong graph to draw here. ## Personal data The default answer is a **count**. Personal rows come back only from `partyMemberCheck(party, name)`, i.e. when the question is about a named person, and even then only the **birth year** — the register publishes the full date and a year is enough to tell two people apart. Never republish a bulk member list when an aggregate answers the question. ## Limits - The register publishes no count, only the list, and one live party's export is a third of a megabyte — so the counting has to happen in code, and plain requests are not enough here: they would put nearly nine thousand people's names in front of you instead of the number you asked for. - The chooser lists **two** tables: `registrisse kantud` (14 live parties) and `registrist kustutatud` (17 struck off). They are not distinguished by markup, only by the heading between them — counting them together doubles Estonia's parties. `politicalParties()` returns `status` per row. - A struck-off party exports an **empty** member list. That is the register's answer, not a failed download. - The export is a snapshot taken at request time; report `retrievedAt`. - Historical aggregates live in a Power BI page (`https://ariregister.rik.ee/eng/statistics/political_parties`) that only renders in a browser. ## Verify The CSV must arrive as `text/csv` with the register's own header — `First name;Last name;Date of birth;Date of starting membership;Suspension of membership in political party`, semicolon-delimited, UTF-8 with BOM. The module throws when that header is missing, which is what tells a real empty list from an HTML error page. ## Module API partyMembership(party) -> {source, page, party, regCode, status, retrievedAt, totals, note} partyMembershipRanking() -> {source, page, retrievedAt, totals, rows, note}