57 lines
2.2 KiB
Python
57 lines
2.2 KiB
Python
"""Dynamic slot generation.
|
|
|
|
Slots are generated from runtime settings (working hours, slot duration,
|
|
default capacity) and per-day `FacilitySchedule` overrides (capacity for the
|
|
day, days off). Generation is idempotent — re-running updates existing slots
|
|
instead of duplicating them.
|
|
"""
|
|
from datetime import datetime, timedelta
|
|
|
|
from apps.core.settings_service import SettingsService
|
|
from apps.reservations.models import FacilitySchedule, Slot
|
|
|
|
|
|
class SlotService:
|
|
def generate_slots(self, facility, day, line=None) -> int:
|
|
schedule = FacilitySchedule.objects.filter(facility=facility, date=day).first()
|
|
if schedule is not None and not schedule.is_open:
|
|
return 0 # day off
|
|
|
|
service = SettingsService()
|
|
if schedule is not None and schedule.start_time:
|
|
start_str = schedule.start_time.strftime("%H:%M")
|
|
else:
|
|
start_str = service.get("reservation.working_hours_start", "08:00")
|
|
if schedule is not None and schedule.end_time:
|
|
end_str = schedule.end_time.strftime("%H:%M")
|
|
else:
|
|
end_str = service.get("reservation.working_hours_end", "17:00")
|
|
duration = int(service.get("reservation.slot_duration_minutes", 30))
|
|
if schedule is not None:
|
|
capacity = schedule.capacity
|
|
else:
|
|
capacity = int(service.get("reservation.default_capacity", 2))
|
|
|
|
if duration <= 0:
|
|
raise ValueError("Slot duration must be positive.")
|
|
|
|
start_t = datetime.strptime(start_str, "%H:%M").time()
|
|
end_t = datetime.strptime(end_str, "%H:%M").time()
|
|
current = datetime.combine(day, start_t)
|
|
end_dt = datetime.combine(day, end_t)
|
|
|
|
created = 0
|
|
while current + timedelta(minutes=duration) <= end_dt:
|
|
slot_end = (current + timedelta(minutes=duration)).time()
|
|
_, was_created = Slot.objects.update_or_create(
|
|
facility=facility,
|
|
line=line,
|
|
date=day,
|
|
start_time=current.time(),
|
|
defaults={"end_time": slot_end, "capacity": capacity},
|
|
)
|
|
if was_created:
|
|
created += 1
|
|
current += timedelta(minutes=duration)
|
|
return created
|