Files
F-r-ldraledigplannerare/backend/app/services/vacation_days_service.py
T
2026-06-01 16:48:21 +02:00

62 lines
2.1 KiB
Python

"""Business logic for vacation days.
The service owns rules; the repository only persists. Routers call services, not
repositories directly. This is the REFERENCE service — keep services thin and
free of HTTP/DB details.
"""
from datetime import datetime
from uuid import UUID, uuid4
from app.entities.vacation_days import VacationDays
from app.repositories.vacation_days_repository import VacationDaysRepository
from app.utils.errors import NotFoundError, ValidationError
class VacationDaysService:
def __init__(self, repo: VacationDaysRepository) -> None:
self._repo = repo
async def upsert(
self,
personal_data_uuid: UUID,
workspace_id: UUID,
year: int,
total_days: int,
saved_days_in: int = 0,
) -> VacationDays:
"""Create or update the (parent, year) vacation entry.
Raises ValidationError on negative inputs (schema also guards this, but a
service should not trust its caller).
"""
if total_days < 0 or saved_days_in < 0:
raise ValidationError("Vacation day counts cannot be negative")
existing = await self._repo.get_by_parent_year(personal_data_uuid, year)
if existing is not None:
existing.total_days = total_days
existing.saved_days_in = saved_days_in
return await self._repo.update(existing.id, existing)
entity = VacationDays(
id=uuid4(),
personal_data_uuid=personal_data_uuid,
workspace_id=workspace_id,
year=year,
total_days=total_days,
saved_days_in=saved_days_in,
created_at=datetime.now(),
updated_at=datetime.now(),
)
return await self._repo.create(entity)
async def get(self, vacation_days_id: UUID) -> VacationDays:
entity = await self._repo.get_by_id(vacation_days_id)
if entity is None:
raise NotFoundError(f"VacationDays {vacation_days_id} not found")
return entity
async def list_for_workspace(self, workspace_id: UUID) -> list[VacationDays]:
return await self._repo.list(workspace_id=workspace_id)