feat: extend inventory and administration workflows

This commit is contained in:
Marcel Peterkau
2026-07-22 22:26:02 +02:00
parent aeaaca1459
commit 070684d9bc
17 changed files with 1342 additions and 69 deletions
+58 -3
View File
@@ -38,6 +38,7 @@ def test_repository_creates_transparent_member_record(tmp_path) -> None:
assert raw["person"]["first_name"] == "Ada"
assert raw["person"]["nickname"] == "Enchantress"
assert raw["schema_version"] == 1
assert raw["membership"]["ended_at"] == ""
assert raw["content_hash"]
@@ -57,6 +58,22 @@ def test_search_matches_name_email_number_and_german_birth_date(tmp_path) -> Non
assert [result.member_id for result in repository.search(query)] == [member.member_id]
def test_past_membership_end_sets_status_to_ended(tmp_path) -> None:
repository = MemberRepository(tmp_path)
repository.initialize()
member = repository.create_member(first_name="Former", last_name="Member")
member.status = "active"
member.accepted_at = "2020-01-01"
member.membership_started_at = "2020-01-01"
member.membership_ended_at = "2020-12-31"
repository.save_member(member)
loaded = repository.get_member(member.member_id)
assert loaded.membership_ended_at == "2020-12-31"
assert loaded.status == "ended"
def test_events_are_appended_and_changes_do_not_leak_values(tmp_path) -> None:
repository = MemberRepository(tmp_path)
repository.initialize()
@@ -145,7 +162,6 @@ def test_automatic_member_numbers_are_sequential_and_preview_does_not_consume(tm
first = repository.create_member(first_name="First", last_name="Member")
second = repository.create_member(first_name="Second", last_name="Member")
assert first.member_number == "CCMA-0001"
assert second.member_number == "CCMA-0002"
assert repository.preview_member_number() == "CCMA-0003"
@@ -286,6 +302,46 @@ def test_asset_can_be_assigned_and_returned_to_single_member(tmp_path) -> None:
assert repository.list_member_assets(member.member_id) == []
def test_member_owned_asset_is_kept_in_central_inventory(tmp_path) -> None:
repository = MemberRepository(tmp_path)
repository.initialize()
owner = repository.create_member(first_name="Ada", last_name="Lovelace")
asset = repository.create_asset(
label="3D-Drucker",
owner_type="member",
owner_member_id=owner.member_id,
custody_type="club",
location="Clubraum / Werkstatt",
handed_over_at="2026-07-22",
condition="gebraucht, funktionsfähig",
estimated_value="450.00",
)
loaded = repository.get_asset(asset.asset_id)
assert loaded.owner_member_id == owner.member_id
assert loaded.custody_type == "club"
assert loaded.location == "Clubraum / Werkstatt"
assert [item.asset_id for item in repository.list_member_owned_assets(owner.member_id)] == [
asset.asset_id
]
assert repository.list_member_assets(owner.member_id) == []
assert repository.list_assets()[0].asset_id == asset.asset_id
assert repository.get_events(owner.member_id)[-1].event_type == "member_asset_registered"
def test_member_ownership_requires_existing_member(tmp_path) -> None:
repository = MemberRepository(tmp_path)
repository.initialize()
with pytest.raises(RepositoryError, match="Mitglied"):
repository.create_asset(
label="Privater Beamer",
owner_type="member",
owner_member_id="missing-member",
)
def test_asset_assignment_is_audited_on_asset_and_member(tmp_path) -> None:
repository = MemberRepository(tmp_path)
repository.initialize()
@@ -423,6 +479,5 @@ def test_housekeeper_reports_json_hash_mismatch(tmp_path) -> None:
findings = Housekeeper(repository).run()
assert any(
finding.code == "json_hash_mismatch" and finding.member_id == member.member_id
for finding in findings
finding.code == "json_hash_mismatch" and finding.member_id == member.member_id for finding in findings
)