125 lines
3.9 KiB
Python
125 lines
3.9 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import date
|
|
from decimal import Decimal
|
|
|
|
from mousehold_api import models
|
|
from mousehold_api.services.settlement import calculate_settlement
|
|
from mousehold_domain import FinancialEventStatus, FinancialEventType
|
|
from sqlalchemy.orm import Session
|
|
|
|
|
|
def test_equal_split_settlement(
|
|
session: Session,
|
|
household_setup: dict[str, str],
|
|
) -> None:
|
|
event = models.FinancialEvent(
|
|
household_id=household_setup["household_id"],
|
|
payment_account_id=household_setup["account_a_id"],
|
|
payer_user_id=household_setup["user_a_id"],
|
|
event_type=FinancialEventType.EXPENSE,
|
|
status=FinancialEventStatus.CONFIRMED,
|
|
event_date=date(2026, 1, 1),
|
|
amount=Decimal("120.00"),
|
|
currency="EUR",
|
|
merchant="Groceries",
|
|
)
|
|
session.add(event)
|
|
session.flush()
|
|
session.add_all(
|
|
[
|
|
models.SplitLine(
|
|
event_id=event.id,
|
|
user_id=household_setup["user_a_id"],
|
|
share_amount=Decimal("60.00"),
|
|
),
|
|
models.SplitLine(
|
|
event_id=event.id,
|
|
user_id=household_setup["user_b_id"],
|
|
share_amount=Decimal("60.00"),
|
|
),
|
|
]
|
|
)
|
|
session.commit()
|
|
|
|
summary = calculate_settlement(session, household_id=household_setup["household_id"])
|
|
|
|
assert len(summary.suggested_transfers) == 1
|
|
transfer = summary.suggested_transfers[0]
|
|
assert transfer.from_user_id == household_setup["user_b_id"]
|
|
assert transfer.to_user_id == household_setup["user_a_id"]
|
|
assert transfer.amount == Decimal("60.00")
|
|
|
|
|
|
def test_shared_neutral_account_is_excluded(
|
|
session: Session,
|
|
household_setup: dict[str, str],
|
|
) -> None:
|
|
event = models.FinancialEvent(
|
|
household_id=household_setup["household_id"],
|
|
payment_account_id=household_setup["shared_account_id"],
|
|
payer_user_id=household_setup["user_a_id"],
|
|
event_type=FinancialEventType.EXPENSE,
|
|
status=FinancialEventStatus.CONFIRMED,
|
|
event_date=date(2026, 1, 1),
|
|
amount=Decimal("100.00"),
|
|
currency="EUR",
|
|
)
|
|
session.add(event)
|
|
session.flush()
|
|
session.add_all(
|
|
[
|
|
models.SplitLine(
|
|
event_id=event.id,
|
|
user_id=household_setup["user_a_id"],
|
|
share_amount=Decimal("50.00"),
|
|
),
|
|
models.SplitLine(
|
|
event_id=event.id,
|
|
user_id=household_setup["user_b_id"],
|
|
share_amount=Decimal("50.00"),
|
|
),
|
|
]
|
|
)
|
|
session.commit()
|
|
|
|
summary = calculate_settlement(session, household_id=household_setup["household_id"])
|
|
|
|
assert summary.included_event_ids == []
|
|
assert summary.excluded_event_ids == [event.id]
|
|
assert summary.suggested_transfers == []
|
|
|
|
|
|
def test_announced_and_outstanding_are_excluded_by_default(
|
|
session: Session,
|
|
household_setup: dict[str, str],
|
|
) -> None:
|
|
event = models.FinancialEvent(
|
|
household_id=household_setup["household_id"],
|
|
payment_account_id=household_setup["account_a_id"],
|
|
payer_user_id=household_setup["user_a_id"],
|
|
event_type=FinancialEventType.EXPENSE,
|
|
status=FinancialEventStatus.OUTSTANDING,
|
|
event_date=date(2026, 1, 1),
|
|
amount=Decimal("80.00"),
|
|
currency="EUR",
|
|
)
|
|
session.add(event)
|
|
session.flush()
|
|
session.add(
|
|
models.SplitLine(
|
|
event_id=event.id, user_id=household_setup["user_b_id"], share_amount=Decimal("80.00")
|
|
)
|
|
)
|
|
session.commit()
|
|
|
|
default_summary = calculate_settlement(session, household_id=household_setup["household_id"])
|
|
forecast_summary = calculate_settlement(
|
|
session,
|
|
household_id=household_setup["household_id"],
|
|
include_announced=True,
|
|
)
|
|
|
|
assert default_summary.suggested_transfers == []
|
|
assert forecast_summary.suggested_transfers[0].amount == Decimal("80.00")
|