Let a day removed from a period stay removed

Taking one day out of a period the planner placed did nothing that
lasted: the period still asked for a full week, so the next sync put the
day straight back. The option was disabled rather than lying about it.

A removed day is now recorded as its own thing — no leave for this
parent, this child, this date — and the planner honours it on every
later sync. It is kept apart from the working-day overrides, which
answer a different question about the calendar rather than about the
plan.

The day belongs to the parent whose band was clicked, so removing one
parent's day leaves their partner's alone; where both parents were to be
off on one funding arrangement, the partner is simply funded on their
own instead. A removed day shortens what the period is asking for rather
than counting as a day the plan failed to find, so the advice about
closing a shortfall does not start arguing for a day nobody wants.

Nothing is removed without a way back: the toast undoes it, and the day
itself is marked in the calendar and offers to restore.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ei7gCZzdd751uZtPzb1Pep
This commit is contained in:
2026-09-19 16:05:17 +02:00
parent 6d92b87bf3
commit 8cfb9c82c6
39 changed files with 2362 additions and 31 deletions
+33
View File
@@ -27,6 +27,7 @@ from app.repositories.day_override_repository import DayOverrideRepository
from app.repositories.leave_wish_repository import LeaveWishRepository
from app.repositories.parental_leave_repository import ParentalLeaveRepository
from app.repositories.personal_data_repository import PersonalDataRepository
from app.repositories.planned_day_exclusion_repository import PlannedDayExclusionRepository
from app.repositories.planned_leave_repository import PlannedLeaveRepository
from app.repositories.tip_dismissal_repository import TipDismissalRepository
from app.repositories.unit_of_work import UnitOfWork
@@ -41,6 +42,9 @@ from app.repositories_impl.sqlite.day_override_repository import SQLiteDayOverri
from app.repositories_impl.sqlite.leave_wish_repository import SQLiteLeaveWishRepository
from app.repositories_impl.sqlite.parental_leave_repository import SQLiteParentalLeaveRepository
from app.repositories_impl.sqlite.personal_data_repository import SQLitePersonalDataRepository
from app.repositories_impl.sqlite.planned_day_exclusion_repository import (
SQLitePlannedDayExclusionRepository,
)
from app.repositories_impl.sqlite.planned_leave_repository import SQLitePlannedLeaveRepository
from app.repositories_impl.sqlite.tip_dismissal_repository import SQLiteTipDismissalRepository
from app.repositories_impl.sqlite.unit_of_work import SQLiteUnitOfWork
@@ -58,6 +62,7 @@ from app.services.child_service import ChildService
from app.services.day_override_service import DayOverrideService
from app.services.leave_wish_service import LeaveWishService
from app.services.personal_data_service import PersonalDataService
from app.services.planned_day_exclusion_service import PlannedDayExclusionService
from app.services.planning_service import PlanningService
from app.services.tips_service import TipsService
from app.services.vacation_days_service import VacationDaysService
@@ -184,6 +189,17 @@ def get_leave_wish_repository(conn: ConnectionDep) -> LeaveWishRepository:
LeaveWishRepositoryDep = Annotated[LeaveWishRepository, Depends(get_leave_wish_repository)]
def get_planned_day_exclusion_repository(conn: ConnectionDep) -> PlannedDayExclusionRepository:
if settings.database_type == "sqlite":
return SQLitePlannedDayExclusionRepository(conn)
raise ValueError(f"Unsupported database_type: {settings.database_type}")
PlannedDayExclusionRepositoryDep = Annotated[
PlannedDayExclusionRepository, Depends(get_planned_day_exclusion_repository)
]
def get_day_override_repository(conn: ConnectionDep) -> DayOverrideRepository:
if settings.database_type == "sqlite":
return SQLiteDayOverrideRepository(conn)
@@ -246,6 +262,21 @@ def get_day_override_service(repo: DayOverrideRepositoryDep) -> DayOverrideServi
DayOverrideServiceDep = Annotated[DayOverrideService, Depends(get_day_override_service)]
def get_planned_day_exclusion_service(
repo: PlannedDayExclusionRepositoryDep,
planned_leave_repo: PlannedLeaveRepositoryDep,
uow: UnitOfWorkDep,
) -> PlannedDayExclusionService:
# `planned_leave_repo` is what makes "remove this day" true immediately
# rather than only after the next sync — see the service's docstring.
return PlannedDayExclusionService(repo, planned_leave_repo, uow=uow)
PlannedDayExclusionServiceDep = Annotated[
PlannedDayExclusionService, Depends(get_planned_day_exclusion_service)
]
def get_calendar_service(day_override_service: DayOverrideServiceDep) -> CalendarService:
return CalendarService(day_override_service)
@@ -339,6 +370,7 @@ def get_allocation_input_loader(
planned_leave_repo: PlannedLeaveRepositoryDep,
leave_wish_repo: LeaveWishRepositoryDep,
day_override_repo: DayOverrideRepositoryDep,
exclusion_repo: PlannedDayExclusionRepositoryDep,
) -> AllocationInputLoader:
return AllocationInputLoader(
workspace_repo=workspace_repo,
@@ -349,6 +381,7 @@ def get_allocation_input_loader(
planned_leave_repo=planned_leave_repo,
leave_wish_repo=leave_wish_repo,
day_override_repo=day_override_repo,
exclusion_repo=exclusion_repo,
)