mirror of
https://git.hiabuto.net/C3MA/CCMA.git
synced 2026-07-01 03:04:52 +02:00
Add asset records, claims, and credit workflows
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import json
|
||||
from decimal import Decimal
|
||||
|
||||
import pytest
|
||||
|
||||
from ccma.domain.contributions import claim_balance
|
||||
from ccma.storage.repository import (
|
||||
MemberRepository,
|
||||
RepositoryError,
|
||||
@@ -238,3 +240,139 @@ def test_organization_sender_data_is_stored_centrally(tmp_path) -> None:
|
||||
organization = repository.get_configuration()["organization"]
|
||||
assert organization["street"] == "Testweg 1"
|
||||
assert organization["iban"] == "DE89370400440532013000"
|
||||
|
||||
|
||||
def test_repository_creates_asset_record_and_events(tmp_path) -> None:
|
||||
repository = MemberRepository(tmp_path / "store")
|
||||
repository.initialize()
|
||||
|
||||
asset = repository.create_asset(
|
||||
label="Clubraumschlüssel A12",
|
||||
category="key",
|
||||
inventory_number="KEY-A12",
|
||||
deposit_amount_default="25",
|
||||
)
|
||||
|
||||
asset_dir = repository.assets_root / asset.asset_id
|
||||
assert (asset_dir / "asset.json").is_file()
|
||||
assert (asset_dir / "events.jsonl").is_file()
|
||||
assert (asset_dir / "files").is_dir()
|
||||
loaded = repository.get_asset(asset.asset_id)
|
||||
assert loaded.label == "Clubraumschlüssel A12"
|
||||
assert loaded.deposit_amount_default == "25.00"
|
||||
|
||||
|
||||
def test_asset_can_be_assigned_and_returned_to_single_member(tmp_path) -> None:
|
||||
repository = MemberRepository(tmp_path)
|
||||
repository.initialize()
|
||||
member = repository.create_member(first_name="Ada", last_name="Lovelace")
|
||||
other = repository.create_member(first_name="Grace", last_name="Hopper")
|
||||
asset = repository.create_asset(label="Transponder 01")
|
||||
|
||||
repository.assign_asset(asset.asset_id, member.member_id)
|
||||
assigned = repository.get_asset(asset.asset_id)
|
||||
assert assigned.status == "issued"
|
||||
assert assigned.current_holder_member_id == member.member_id
|
||||
assert [item.asset_id for item in repository.list_member_assets(member.member_id)] == [asset.asset_id]
|
||||
with pytest.raises(RepositoryError, match="bereits einem Mitglied zugeordnet"):
|
||||
repository.assign_asset(asset.asset_id, other.member_id)
|
||||
|
||||
repository.return_asset(asset.asset_id)
|
||||
returned = repository.get_asset(asset.asset_id)
|
||||
assert returned.status == "available"
|
||||
assert returned.current_holder_member_id == ""
|
||||
assert repository.list_member_assets(member.member_id) == []
|
||||
|
||||
|
||||
def test_asset_assignment_is_audited_on_asset_and_member(tmp_path) -> None:
|
||||
repository = MemberRepository(tmp_path)
|
||||
repository.initialize()
|
||||
member = repository.create_member(first_name="Key", last_name="Holder", member_number="0042")
|
||||
asset = repository.create_asset(label="Clubraumschlüssel")
|
||||
|
||||
repository.assign_asset(asset.asset_id, member.member_id)
|
||||
repository.return_asset(asset.asset_id)
|
||||
|
||||
asset_events = [event.event_type for event in repository.get_asset_events(asset.asset_id)]
|
||||
member_events = [event.event_type for event in repository.get_events(member.member_id)]
|
||||
assert asset_events == ["asset_created", "asset_issued", "asset_returned"]
|
||||
assert "asset_assigned" in member_events
|
||||
assert "asset_returned" in member_events
|
||||
|
||||
|
||||
def test_asset_deposit_cannot_change_while_issued(tmp_path) -> None:
|
||||
repository = MemberRepository(tmp_path)
|
||||
repository.initialize()
|
||||
member = repository.create_member(first_name="Ada", last_name="Lovelace")
|
||||
asset = repository.create_asset(label="Clubraumschlüssel", deposit_amount_default="25")
|
||||
repository.assign_asset(asset.asset_id, member.member_id)
|
||||
|
||||
issued = repository.get_asset(asset.asset_id)
|
||||
issued.deposit_amount_default = "35"
|
||||
with pytest.raises(RepositoryError, match="Kaution kann nur geändert werden"):
|
||||
repository.save_asset(issued)
|
||||
|
||||
|
||||
def test_asset_deposit_can_change_when_not_issued(tmp_path) -> None:
|
||||
repository = MemberRepository(tmp_path)
|
||||
repository.initialize()
|
||||
asset = repository.create_asset(label="Clubraumschlüssel", deposit_amount_default="25")
|
||||
|
||||
asset.deposit_amount_default = "35"
|
||||
repository.save_asset(asset)
|
||||
|
||||
updated = repository.get_asset(asset.asset_id)
|
||||
assert updated.deposit_amount_default == "35.00"
|
||||
|
||||
|
||||
def test_manual_asset_claim_is_linked_to_member_and_asset(tmp_path) -> None:
|
||||
repository = MemberRepository(tmp_path)
|
||||
repository.initialize()
|
||||
member = repository.create_member(first_name="Ada", last_name="Lovelace")
|
||||
asset = repository.create_asset(label="Clubraumschlüssel")
|
||||
repository.assign_asset(asset.asset_id, member.member_id)
|
||||
|
||||
result = repository.create_manual_claim(
|
||||
member.member_id,
|
||||
title="Kaution Clubraumschlüssel",
|
||||
amount="25.00",
|
||||
due_date="2026-06-26",
|
||||
description="Kaution für Schlüssel",
|
||||
claim_type="asset_deposit",
|
||||
references={"asset_id": asset.asset_id},
|
||||
)
|
||||
|
||||
claim = result["claim"]
|
||||
loaded_claim = repository.get_contributions(member.member_id).claims[0]
|
||||
assert claim["claim_id"] == loaded_claim["claim_id"]
|
||||
assert loaded_claim["origin"]["asset_id"] == asset.asset_id
|
||||
assert repository.get_asset_events(asset.asset_id)[-1].event_type == "asset_claim_created"
|
||||
|
||||
|
||||
def test_negative_claim_can_be_settled_with_credit(tmp_path) -> None:
|
||||
repository = MemberRepository(tmp_path)
|
||||
repository.initialize()
|
||||
member = repository.create_member(first_name="Ada", last_name="Lovelace")
|
||||
asset = repository.create_asset(label="Clubraumschlüssel")
|
||||
repository.assign_asset(asset.asset_id, member.member_id)
|
||||
claim = repository.create_manual_claim(
|
||||
member.member_id,
|
||||
title="Kautionsrückzahlung",
|
||||
amount="-25.00",
|
||||
due_date="2026-06-26",
|
||||
claim_type="asset_refund",
|
||||
references={"asset_id": asset.asset_id},
|
||||
)["claim"]
|
||||
|
||||
repository.record_credit(
|
||||
member.member_id,
|
||||
str(claim["claim_id"]),
|
||||
credit_date="2026-06-26",
|
||||
amount="25.00",
|
||||
allocation_amount="25.00",
|
||||
reference="Bar ausgezahlt",
|
||||
)
|
||||
|
||||
data, loaded_claim = repository.get_claim(member.member_id, str(claim["claim_id"]))
|
||||
assert claim_balance(data, loaded_claim) == Decimal("0.00")
|
||||
assert data.credits[0]["amount"] == "25.00"
|
||||
|
||||
Reference in New Issue
Block a user