Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.18.0] - 2026-08-03

### Added

- Boliglån: Functionality to search for cases.

## [2.17.4] - 2026-07-08

### Fixed
Expand Down
7 changes: 6 additions & 1 deletion itk_dev_shared_components/boliglaan/common.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""This module contains functions to perform common actions in Boliglån."""

import time
from typing import Literal
from typing import Any, Literal

import uiautomation

Expand Down Expand Up @@ -80,3 +80,8 @@ def save_case():
# Handle popup
popup = boliglaan.WindowControl(Name="Kvittering", searchDepth=1)
popup.ButtonControl(Name="Gem/Send breve", searchDepth=1).GetInvokePattern().Invoke()


def get_grid_value(grid_pattern: uiautomation.GridPattern, row: int, column: int) -> Any:
"""Helper function to get the value of a grid item."""
return grid_pattern.GetItem(row, column).GetPattern(uiautomation.PatternId.ValuePattern).Value
28 changes: 9 additions & 19 deletions itk_dev_shared_components/boliglaan/search/search_advis.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

from dataclasses import dataclass
from datetime import date
from typing import Any, Literal

import uiautomation
from typing import Literal

from itk_dev_shared_components.boliglaan import common

Expand Down Expand Up @@ -44,9 +42,6 @@ def search_advis(cpr: str | None = None, date_from: date | None = None, date_to:
date_from: The date to search from.
date_to: The date to search to.
types: The types of advis to search for. If None all types are chosen.

Raises:
ValueError: If 'All' is not alone in the types list.
"""
boliglaan = common.get_boliglaan()
boliglaan.SendKeys("{Ctrl}T")
Expand Down Expand Up @@ -80,8 +75,8 @@ def select_advis(cpr: str, case_number: str):
grid_pattern = grid.GetGridPattern()

for row in range(grid_pattern.RowCount):
row_case_number = _get_grid_value(grid_pattern, row, 1)
case_cpr = _get_grid_value(grid_pattern, row, 2)
row_case_number = common.get_grid_value(grid_pattern, row, 1)
case_cpr = common.get_grid_value(grid_pattern, row, 2)

if case_cpr == cpr and row_case_number == case_number:
grid_pattern.GetItem(row, 0).DoubleClick(simulateMove=False)
Expand All @@ -100,21 +95,16 @@ def get_advis_list() -> list[Advis]:
result = []

for row in range(grid_pattern.RowCount):
date_str: str = _get_grid_value(grid_pattern, row, 0)
case_number = _get_grid_value(grid_pattern, row, 1)
cpr = _get_grid_value(grid_pattern, row, 2)
type_ = _get_grid_value(grid_pattern, row, 3)
state = _get_grid_value(grid_pattern, row, 4)
case_type = _get_grid_value(grid_pattern, row, 6)
date_str: str = common.get_grid_value(grid_pattern, row, 0)
case_number = common.get_grid_value(grid_pattern, row, 1)
cpr = common.get_grid_value(grid_pattern, row, 2)
type_ = common.get_grid_value(grid_pattern, row, 3)
state = common.get_grid_value(grid_pattern, row, 4)
case_type = common.get_grid_value(grid_pattern, row, 6)

day, month, year = (int(part) for part in date_str.split("-"))
date_ = date(year, month, day)

result.append(Advis(date=date_, cpr=cpr, case_number=case_number, type=type_, state=state, case_type=case_type))

return result


def _get_grid_value(grid_pattern: uiautomation.GridPattern, row: int, column: int) -> Any:
"""Helper function to get the value of a grid item."""
return grid_pattern.GetItem(row, column).GetPattern(uiautomation.PatternId.ValuePattern).Value
146 changes: 146 additions & 0 deletions itk_dev_shared_components/boliglaan/search/search_cases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
"""This module contains functions to search for cases
and handling the cases search results.
"""

from dataclasses import dataclass
from typing import Literal

from itk_dev_shared_components.boliglaan import common


CaseState = Literal[
"Afslået",
"Afventer bevilling",
"Bevilget",
"Udbetalt",
"Afvikling - frivillig",
"Afvikling - misligholdt afdrag kautionslån",
"Afvikling - misligholdt kautionslån",
"Afvikling - 5 års løbetid",
"Afvikling - overskridelse af indkomstgrænse",
"Afvikling - fraflyttet",
"Afvikling - rentefri",
"Gældssaneret",
"Afskrevet - gældssaneret",
"Afskrevet - lån uerholdeligt",
"Afskrevet - dødsfald",
"Afskrevet - RIM (Restance Inddrivelses Myndighed)",
"Overført til anden person",
"Overført/Annulleret",
"Tilbageført",
"Indfriet",
"Annulleret lån",
"Annulleret ansøgning"
]


CaseType = Literal[
"Pligtlån 5 års løbetid §56, §57",
"Pligtlån sanering §54",
"Pligtlån pensionister §54",
"Pligtlån enkeltværelse §54",
"Pligtlån genhusning §54",
"Pligtlån ældrebolig §54",
"Flygtningelån 100% 5 års løbetid §66, §67",
"Flygtningelån 100% sanering §66, §67",
"Flygtningelån 100% pensionister §66, §67",
"Flygtninglån 50% 5 års løbetid §68",
"Kautionslån kaution §59",
"Kautionslån flygtninge §68",
"Kommune lån §59",
"Garanti for istandsættelse"
]


@dataclass
class Case:
"""A dataclass representing a case from the case search result."""
case_number: str
cpr: str
person_name: str
address: str
case_type: str
case_state: str


def search_cases(cpr: str | None = None, street: str | None = None, types: tuple[CaseType] | None = None, states: tuple[CaseState] | None = None):
"""Search for cases.

Args:
cpr: The CPR number to look for.
street: The street name to look for.
types: The case types to look for.
states: The case states to look for.
"""
boliglaan = common.get_boliglaan()
boliglaan.SendKeys("{Ctrl}B")

popup = boliglaan.WindowControl(Name="Udsøg lånesager", searchDepth=1)

if cpr:
popup.TextControl(Name="Personnummer:").GetNextSiblingControl().GetValuePattern().SetValue(cpr)

if street:
popup.EditControl(AutomationId="vejSearchEdit").EditControl().GetValuePattern().SetValue(street)

group = popup.GroupControl(Name="Lånetype", searchDepth=3)
if types is None:
group.CheckBoxControl(Name='Alle valgt').GetTogglePattern().SetToggleState(1)
else:
group.CheckBoxControl(Name='Alle valgt').GetTogglePattern().SetToggleState(0)

for type_ in types:
group.CheckBoxControl(Name=type_).GetTogglePattern().SetToggleState(1, waitTime=0)

group = popup.GroupControl(Name="Lånestatus", searchDepth=3)
if states is None:
group.CheckBoxControl(Name='Alle valgt').GetTogglePattern().SetToggleState(1)
else:
group.CheckBoxControl(Name='Alle valgt').GetTogglePattern().SetToggleState(0)

for state in states:
group.CheckBoxControl(Name=state).GetTogglePattern().SetToggleState(1, waitTime=0)

popup.ButtonControl(Name="Søg").Click(simulateMove=False)


def get_case_list() -> list[Case]:
"""Get the case search results as a list of Case objects."""
boliglaan = common.get_boliglaan()

grid = boliglaan.TabControl(Name="TabbedGroup", searchDepth=4).GroupControl(Name="Sager").DataGridControl(AutomationId="LaanesagerGridControl")
grid_pattern = grid.GetGridPattern()

result = []

for row in range(grid_pattern.RowCount):
new_case = Case(
case_number=common.get_grid_value(grid_pattern, row, 0),
cpr=common.get_grid_value(grid_pattern, row, 1),
person_name=common.get_grid_value(grid_pattern, row, 2),
case_state=common.get_grid_value(grid_pattern, row, 3),
case_type=common.get_grid_value(grid_pattern, row, 4),
address=common.get_grid_value(grid_pattern, row, 5)
)

result.append(new_case)

return result


def select_case(cpr: str, case_number: str):
"""Select the case from the case search result with the given cpr and case number."""
boliglaan = common.get_boliglaan()

grid = boliglaan.TabControl(Name="TabbedGroup", searchDepth=4).GroupControl(Name="Sager").DataGridControl(AutomationId="LaanesagerGridControl")
grid_pattern = grid.GetGridPattern()

for row in range(grid_pattern.RowCount):
row_case_number = common.get_grid_value(grid_pattern, row, 0)
case_cpr = common.get_grid_value(grid_pattern, row, 1)

if case_cpr == cpr and row_case_number == case_number:
grid_pattern.GetItem(row, 0).DoubleClick(simulateMove=False)
return

raise LookupError(f"Couldn't find case: {cpr} - {case_number}")
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "itk_dev_shared_components"
version = "2.17.4"
version = "2.18.0"
authors = [
{ name="ITK Development", email="itk-rpa@mkb.aarhus.dk" },
]
Expand Down
Loading