Rework balances around per-parent days left and deduce the partner from FK
Manual entry now takes one parent's sjukpenningnivå, lägstanivå and dubbeldagar left (plus optional reserved days) and derives the rest in build_snapshot, shared with the scraper. The scraper also reads the family panel and exposes a partner deduction; with two parents it is saved as a 'deduced' snapshot (migration 002). Parent count is the single source of entitlement: one member gets 480 days and 96 savable at age 4, two get 240 and 48 each. Workspaces are capped at two parents. Also lands the in-flight squash of migrations 002–011 into the initial schema and the removal of planning_mode. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
"""Tests for the Workspace service.
|
||||
|
||||
Covers workspace creation/update, with a focus on the `planning_mode` field
|
||||
(explicit solo/couple planning intent — not inferred from member count), plus
|
||||
Covers workspace creation/update (name only — whether a family plans solo or
|
||||
together is derived from member count, not a stored field; see
|
||||
`test_allocation_service.py`/`test_allocation_service_branches.py` for the
|
||||
allocator-side "couple wish-assignment gates on parent count" coverage), plus
|
||||
renaming/removing a placeholder partner (`rename_member` / `remove_member`).
|
||||
"""
|
||||
|
||||
@@ -49,64 +51,23 @@ async def _make_inviter(user_repo: SQLiteUserRepository, personal_data_uuid: UUI
|
||||
return user.id
|
||||
|
||||
|
||||
class TestWorkspacePlanningMode:
|
||||
"""Test planning_mode defaults and validation."""
|
||||
class TestWorkspaceUpdate:
|
||||
"""Workspace name updates (planning mode is no longer a stored field)."""
|
||||
|
||||
async def test_create_workspace_defaults_to_solo(
|
||||
async def test_update_name(
|
||||
self,
|
||||
workspace_service: WorkspaceService,
|
||||
) -> None:
|
||||
"""A newly created workspace defaults to solo planning mode."""
|
||||
ws = await workspace_service.create_workspace("Test WS")
|
||||
assert ws.planning_mode == "solo"
|
||||
|
||||
async def test_update_planning_mode_to_couple(
|
||||
self,
|
||||
workspace_service: WorkspaceService,
|
||||
) -> None:
|
||||
"""Updating planning_mode to a valid value ('couple') succeeds."""
|
||||
ws = await workspace_service.create_workspace("Test WS")
|
||||
updated = await workspace_service.update_workspace(ws.id, planning_mode="couple")
|
||||
assert updated.planning_mode == "couple"
|
||||
|
||||
async def test_update_planning_mode_back_to_solo(
|
||||
self,
|
||||
workspace_service: WorkspaceService,
|
||||
) -> None:
|
||||
"""Updating planning_mode back to 'solo' succeeds."""
|
||||
ws = await workspace_service.create_workspace("Test WS")
|
||||
await workspace_service.update_workspace(ws.id, planning_mode="couple")
|
||||
updated = await workspace_service.update_workspace(ws.id, planning_mode="solo")
|
||||
assert updated.planning_mode == "solo"
|
||||
|
||||
async def test_update_planning_mode_invalid_raises(
|
||||
self,
|
||||
workspace_service: WorkspaceService,
|
||||
) -> None:
|
||||
"""An invalid planning_mode value raises ValidationError."""
|
||||
ws = await workspace_service.create_workspace("Test WS")
|
||||
with pytest.raises(ValidationError, match="planning_mode must be one of"):
|
||||
await workspace_service.update_workspace(ws.id, planning_mode="throuple")
|
||||
|
||||
async def test_update_planning_mode_missing_workspace_raises(
|
||||
self,
|
||||
workspace_service: WorkspaceService,
|
||||
) -> None:
|
||||
"""Updating planning_mode on a missing workspace raises NotFoundError."""
|
||||
with pytest.raises(NotFoundError):
|
||||
await workspace_service.update_workspace(uuid4(), planning_mode="couple")
|
||||
|
||||
async def test_update_name_and_planning_mode_together(
|
||||
self,
|
||||
workspace_service: WorkspaceService,
|
||||
) -> None:
|
||||
"""Multiple fields can be updated in the same call."""
|
||||
ws = await workspace_service.create_workspace("Old Name")
|
||||
updated = await workspace_service.update_workspace(
|
||||
ws.id, name="New Name", planning_mode="couple"
|
||||
)
|
||||
updated = await workspace_service.update_workspace(ws.id, name="New Name")
|
||||
assert updated.name == "New Name"
|
||||
assert updated.planning_mode == "couple"
|
||||
|
||||
async def test_update_missing_workspace_raises_not_found(
|
||||
self,
|
||||
workspace_service: WorkspaceService,
|
||||
) -> None:
|
||||
with pytest.raises(NotFoundError):
|
||||
await workspace_service.update_workspace(uuid4(), name="Whatever")
|
||||
|
||||
|
||||
class TestRenameMember:
|
||||
@@ -182,6 +143,20 @@ class TestRenameMember:
|
||||
with pytest.raises(ValidationError, match="empty or whitespace-only"):
|
||||
await workspace_service.add_placeholder_parent(seeded_ids.workspace_id, " ")
|
||||
|
||||
async def test_add_placeholder_beyond_two_parents_raises_validation_error(
|
||||
self,
|
||||
workspace_service: WorkspaceService,
|
||||
seeded_ids: SeededIds,
|
||||
) -> None:
|
||||
"""A workspace is capped at 2 parents — `seeded_ids.personal_data_uuid`
|
||||
(1) plus one placeholder (2) already fill it; a third is refused."""
|
||||
await workspace_service.add_placeholder_parent(seeded_ids.workspace_id, "Sam")
|
||||
with pytest.raises(ValidationError, match="maximum number of parents"):
|
||||
await workspace_service.add_placeholder_parent(seeded_ids.workspace_id, "Kim")
|
||||
|
||||
members = await workspace_service.list_members(seeded_ids.workspace_id)
|
||||
assert {m.name for m in members} == {"Test Parent", "Sam"}
|
||||
|
||||
|
||||
class TestRemoveMember:
|
||||
"""Remove (soft-delete) a placeholder partner, guarding against orphaned data."""
|
||||
|
||||
Reference in New Issue
Block a user