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:
@@ -282,3 +282,154 @@ class TestLeaveWishTargetDaysRoundTrip:
|
||||
listed = await client.get(f"/api/leave-wishes/{ws.id}")
|
||||
assert listed.status_code == 200
|
||||
assert listed.json()[0]["target_days"] is None
|
||||
|
||||
|
||||
class TestLeaveWishWantsDubbeldagRoundTrip:
|
||||
"""§Decision A (co-leave, opt-in dubbeldagar) — `wants_dubbeldag` round-trips
|
||||
|
||||
through the router exactly like `target_days` above, and is rejected
|
||||
when `parent_mode` isn't `'both'`.
|
||||
"""
|
||||
|
||||
async def test_create_defaults_to_false(
|
||||
self,
|
||||
client: AsyncClient,
|
||||
connection: aiosqlite.Connection,
|
||||
) -> None:
|
||||
now = datetime.now()
|
||||
workspace_repo = SQLiteWorkspaceRepository(connection)
|
||||
ws = await workspace_repo.create(Workspace(id=uuid4(), name="Familj", created_at=now))
|
||||
await SQLitePersonalDataRepository(connection).create(
|
||||
PersonalData(
|
||||
uuid=_CURRENT_USER_PD_UUID, workspace_id=ws.id, name="Alex", created_at=now
|
||||
)
|
||||
)
|
||||
|
||||
response = await client.post(
|
||||
"/api/leave-wishes",
|
||||
json={
|
||||
"workspace_id": str(ws.id),
|
||||
"child_id": None,
|
||||
"name": "Vårlov",
|
||||
"window_start_month": 3,
|
||||
"window_start_day": 1,
|
||||
"window_end_month": 5,
|
||||
"window_end_day": 31,
|
||||
"target_weeks": 2,
|
||||
"recurrence": "once",
|
||||
"first_year": date.today().year + 1,
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 201
|
||||
assert response.json()["wants_dubbeldag"] is False
|
||||
|
||||
async def test_create_with_both_parent_mode_can_opt_in(
|
||||
self,
|
||||
client: AsyncClient,
|
||||
connection: aiosqlite.Connection,
|
||||
) -> None:
|
||||
now = datetime.now()
|
||||
workspace_repo = SQLiteWorkspaceRepository(connection)
|
||||
ws = await workspace_repo.create(Workspace(id=uuid4(), name="Familj", created_at=now))
|
||||
await SQLitePersonalDataRepository(connection).create(
|
||||
PersonalData(
|
||||
uuid=_CURRENT_USER_PD_UUID, workspace_id=ws.id, name="Alex", created_at=now
|
||||
)
|
||||
)
|
||||
|
||||
response = await client.post(
|
||||
"/api/leave-wishes",
|
||||
json={
|
||||
"workspace_id": str(ws.id),
|
||||
"child_id": None,
|
||||
"name": "Vårlov",
|
||||
"window_start_month": 3,
|
||||
"window_start_day": 1,
|
||||
"window_end_month": 5,
|
||||
"window_end_day": 31,
|
||||
"target_weeks": 2,
|
||||
"recurrence": "once",
|
||||
"first_year": date.today().year + 1,
|
||||
"parent_mode": "both",
|
||||
"wants_dubbeldag": True,
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 201
|
||||
assert response.json()["wants_dubbeldag"] is True
|
||||
|
||||
async def test_create_rejects_wants_dubbeldag_outside_both_mode(
|
||||
self,
|
||||
client: AsyncClient,
|
||||
connection: aiosqlite.Connection,
|
||||
) -> None:
|
||||
now = datetime.now()
|
||||
workspace_repo = SQLiteWorkspaceRepository(connection)
|
||||
ws = await workspace_repo.create(Workspace(id=uuid4(), name="Familj", created_at=now))
|
||||
await SQLitePersonalDataRepository(connection).create(
|
||||
PersonalData(
|
||||
uuid=_CURRENT_USER_PD_UUID, workspace_id=ws.id, name="Alex", created_at=now
|
||||
)
|
||||
)
|
||||
|
||||
response = await client.post(
|
||||
"/api/leave-wishes",
|
||||
json={
|
||||
"workspace_id": str(ws.id),
|
||||
"child_id": None,
|
||||
"name": "Vårlov",
|
||||
"window_start_month": 3,
|
||||
"window_start_day": 1,
|
||||
"window_end_month": 5,
|
||||
"window_end_day": 31,
|
||||
"target_weeks": 2,
|
||||
"recurrence": "once",
|
||||
"first_year": date.today().year + 1,
|
||||
"wants_dubbeldag": True, # parent_mode defaults to 'either'
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 422
|
||||
|
||||
async def test_update_can_toggle_it(
|
||||
self,
|
||||
client: AsyncClient,
|
||||
connection: aiosqlite.Connection,
|
||||
) -> None:
|
||||
now = datetime.now()
|
||||
workspace_repo = SQLiteWorkspaceRepository(connection)
|
||||
ws = await workspace_repo.create(Workspace(id=uuid4(), name="Familj", created_at=now))
|
||||
await SQLitePersonalDataRepository(connection).create(
|
||||
PersonalData(
|
||||
uuid=_CURRENT_USER_PD_UUID, workspace_id=ws.id, name="Alex", created_at=now
|
||||
)
|
||||
)
|
||||
|
||||
create_response = await client.post(
|
||||
"/api/leave-wishes",
|
||||
json={
|
||||
"workspace_id": str(ws.id),
|
||||
"child_id": None,
|
||||
"name": "Vårlov",
|
||||
"window_start_month": 3,
|
||||
"window_start_day": 1,
|
||||
"window_end_month": 5,
|
||||
"window_end_day": 31,
|
||||
"target_weeks": 2,
|
||||
"recurrence": "once",
|
||||
"first_year": date.today().year + 1,
|
||||
"parent_mode": "both",
|
||||
},
|
||||
)
|
||||
assert create_response.status_code == 201
|
||||
wish_id = create_response.json()["id"]
|
||||
assert create_response.json()["wants_dubbeldag"] is False
|
||||
|
||||
update_response = await client.put(
|
||||
f"/api/leave-wishes/{wish_id}",
|
||||
json={"wants_dubbeldag": True},
|
||||
)
|
||||
|
||||
assert update_response.status_code == 200
|
||||
assert update_response.json()["wants_dubbeldag"] is True
|
||||
|
||||
Reference in New Issue
Block a user