Skip to content

law_service

law_service

Service functions for the laws/bills (zákony) page.

get_all_status_labels(data)

Collect unique status values from all tisky.

Parameters:

Name Type Description Default
data PeriodData

Period data containing tisk_lookup.

required

Returns:

Type Description
list[str]

Sorted list of unique status strings.

Source code in pspcz_analyzer/services/law_service.py
def get_all_status_labels(data: PeriodData) -> list[str]:
    """Collect unique status values from all tisky.

    Args:
        data: Period data containing tisk_lookup.

    Returns:
        Sorted list of unique status strings.
    """
    seen: set[str] = set()
    for tisk in data.tisk_lookup.values():
        seen.add(_tisk_status(tisk))
    return sorted(seen)

list_laws(data, search='', status_filter='', topic_filter='', page=1, per_page=20, lang='cs')

List bills with optional search, status, and topic filters, paginated.

Parameters:

Name Type Description Default
data PeriodData

Period data containing tisk_lookup and amendment_data.

required
search str

Optional text search filter on tisk name.

''
status_filter str

Exact status string to match (empty or 'all' = no filter).

''
topic_filter str

Exact topic label to match (empty = no filter).

''
page int

Page number (1-based).

1
per_page int

Results per page.

20
lang str

Language code for topics/summaries.

'cs'

Returns:

Type Description
dict

Dict with keys: rows, total, page, per_page, total_pages.

Source code in pspcz_analyzer/services/law_service.py
def list_laws(
    data: PeriodData,
    search: str = "",
    status_filter: str = "",
    topic_filter: str = "",
    page: int = 1,
    per_page: int = 20,
    lang: str = "cs",
) -> dict:
    """List bills with optional search, status, and topic filters, paginated.

    Args:
        data: Period data containing tisk_lookup and amendment_data.
        search: Optional text search filter on tisk name.
        status_filter: Exact status string to match (empty or 'all' = no filter).
        topic_filter: Exact topic label to match (empty = no filter).
        page: Page number (1-based).
        per_page: Results per page.
        lang: Language code for topics/summaries.

    Returns:
        Dict with keys: rows, total, page, per_page, total_pages.
    """
    tisky = _deduplicate_tisky(data)

    # Filter by search text
    if search:
        search_lower = search.lower()
        tisky = [t for t in tisky if search_lower in t.nazev.lower()]

    # Filter by status (exact match)
    if status_filter and status_filter != "all":
        tisky = [t for t in tisky if _tisk_status(t) == status_filter]

    # Filter by topic
    if topic_filter:
        tisky = [
            t
            for t in tisky
            if topic_filter in (t.topics_en if (lang == "en" and t.topics_en) else t.topics)
        ]

    # Sort by ct descending (newest first)
    tisky.sort(key=lambda t: t.ct, reverse=True)

    total = len(tisky)
    total_pages = max(1, (total + per_page - 1) // per_page)
    page = max(1, min(page, total_pages))

    offset = (page - 1) * per_page
    page_tisky = tisky[offset : offset + per_page]

    rows = [_build_law_row(t, data, lang) for t in page_tisky]

    return {
        "rows": rows,
        "total": total,
        "page": page,
        "per_page": per_page,
        "total_pages": total_pages,
    }

law_detail(data, ct, lang='cs')

Get full detail for a single bill by tisk number.

Parameters:

Name Type Description Default
data PeriodData

Period data.

required
ct int

Tisk number (cislo tisku).

required
lang str

Language code for summaries/topics.

'cs'

Returns:

Type Description
dict | None

Dict with full bill info, or None if ct not found.

Source code in pspcz_analyzer/services/law_service.py
def law_detail(
    data: PeriodData,
    ct: int,
    lang: str = "cs",
) -> dict | None:
    """Get full detail for a single bill by tisk number.

    Args:
        data: Period data.
        ct: Tisk number (cislo tisku).
        lang: Language code for summaries/topics.

    Returns:
        Dict with full bill info, or None if ct not found.
    """
    # Find TiskInfo by ct
    tisk: TiskInfo | None = None
    for t in data.tisk_lookup.values():
        if t.ct == ct:
            tisk = t
            break

    if tisk is None:
        return None

    status = _tisk_status(tisk)
    submitter = _tisk_submitter(tisk)
    law_number = _tisk_law_number(tisk)
    topics = tisk.topics_en if (lang == "en" and tisk.topics_en) else tisk.topics
    summary = tisk.summary_en if (lang == "en" and tisk.summary_en) else tisk.summary

    # Legislative history stages
    history = tisk.history

    # Find all amendment data entries for this ct
    amendment_entries: list[dict] = []
    for (schuze, bod), bill in data.amendment_data.items():
        if bill.ct == ct:
            final_result = bill.final_vote.result if bill.final_vote else ""
            amendment_entries.append(
                {
                    "schuze": schuze,
                    "bod": bod,
                    "amendment_count": bill.amendment_count,
                    "final_result": final_result,
                }
            )

    # Find related votes
    related_votes = _find_votes_for_ct(data, ct)

    return {
        "ct": tisk.ct,
        "nazev": tisk.nazev,
        "period": tisk.period,
        "url": tisk.url,
        "topics": topics,
        "summary": summary,
        "status": status,
        "submitter": submitter,
        "law_number": law_number,
        "history": history,
        "amendment_entries": amendment_entries,
        "has_amendments": len(amendment_entries) > 0,
        "related_votes": related_votes,
    }