codex_services.booking.slot_master.dto
dto
codex_services.booking.slot_master.dto
Pydantic v2 DTO (Data Transfer Objects) for the slot-master booking engine.
All models are immutable (frozen=True via BaseDTO) — the engine does not mutate inputs. No Django imports. Only Python stdlib + pydantic + codex_core.
Imports
from codex_services.booking.slot_master import ( BookingEngineRequest, ServiceRequest, MasterAvailability, EngineResult, BookingChainSolution, )
Classes
ServiceRequest
Bases: BaseDTO
Request for a single service within a booking chain.
The engine treats this as an atomic requirement. It operates with abstract resource IDs (possible_resource_ids) rather than specific business entities.
Fields
service_id (str): Unique identifier of the service. String for universality (can be "5", "uuid-xxx", "task-1" — doesn't matter).
duration_minutes (int): Duration of the service in minutes. Must be > 0.
min_gap_after_minutes (int): Minimum gap (minutes) after this service before the next one in the chain. Default is 0 (no gap). Example: if there is a cooling down period of 30 mins → min_gap_after_minutes=30.
possible_resource_ids (list[str]): List of resource IDs capable of performing this service. The engine chooses an available resource from this list. For RESOURCE_LOCKED mode, this should contain exactly one element.
parallel_group (str | None): Tag for parallel execution group. Services with the same parallel_group can be performed simultaneously by different resources (if overlap_allowed=True is set in the request). None = service is performed independently (standard sequential behavior).
Example
ServiceRequest(
service_id="5",
duration_minutes=60,
possible_resource_ids=["1", "3", "7"],
)
Source code in src/codex_services/booking/slot_master/dto.py
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | |
Attributes
total_block_minutes
property
Return total time that blocks the resource: duration + gap after.
BookingEngineRequest
Bases: BookingRequest
Input request describing the entire desired booking chain.
Orchestrates multiple ServiceRequests into a single search task. Inherits booking_date from BookingRequest.
Fields
service_requests (list[ServiceRequest]): List of services to book. Order is critical for SINGLE_DAY mode — the engine will schedule them in the specified sequence. Minimum 1 service required.
booking_date (date): Target date. Inherited from BookingRequest. Used for SINGLE_DAY and RESOURCE_LOCKED. In MULTI_DAY mode, this represents the date of the first service.
mode (BookingMode): Engine operating strategy. Default is SINGLE_DAY.
overlap_allowed (bool): Allow parallel execution of services by different resources. False (default) — each subsequent service starts only after the previous one (plus its gap) ends. True — resources can work independently; services may start simultaneously if resources are available.
group_size (int): DEPRECATED. Use duplication of ServiceRequest with parallel_group.
max_chain_duration_minutes (int | None): Maximum total duration of the entire booking (from start of first to end of last service). None = no limit.
days_gap (list[int] | None): Day offsets for each service. Used strictly in MULTI_DAY mode.
Example
BookingEngineRequest(
service_requests=[svc_1, svc_2],
booking_date=date(2024, 5, 10),
mode=BookingMode.SINGLE_DAY,
overlap_allowed=True
)
Source code in src/codex_services/booking/slot_master/dto.py
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | |
Attributes
total_duration_minutes
property
Calculate total duration of all services without gap pauses.
total_block_minutes
property
Calculate total blocking time including pauses between services. Used for quick checks: does the chain fit into a given window.
MasterAvailability
Bases: ResourceAvailability
Available time windows of a resource for the slot-master booking type.
Inherits resource_id and free_windows from ResourceAvailability. Adds slot-master-specific fields: buffer_between_minutes and work_start.
Fields
resource_id (str): Resource identifier (inherited). free_windows (list[tuple[datetime, datetime]]): List of (start, end) tuples (inherited). buffer_between_minutes (int): Minimum buffer required between bookings. work_start (datetime | None): Shift start anchor for slot alignment.
Example
MasterAvailability(
resource_id="resource_1",
free_windows=[(datetime(2024,5,10,9,0), datetime(2024,5,10,12,0))],
buffer_between_minutes=10,
)
Source code in src/codex_services/booking/slot_master/dto.py
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | |
SingleServiceSolution
Bases: BookingSolution
Found slot for a single service in a booking chain.
Inherits resource_id, start_time, end_time from BookingSolution. Adds service_id and gap_end_time.
Fields
service_id (str): Reference to the original ServiceRequest.service_id. resource_id (str): Identifier of the resource assigned to this service (inherited). start_time (datetime): Scheduled start time of the service (inherited). end_time (datetime): Scheduled completion time (excluding gap) (inherited). gap_end_time (datetime): End of the blocking period (end_time + gap).
Example
slot = SingleServiceSolution(
service_id="5",
resource_id="1",
start_time=datetime(2024, 5, 10, 10, 0),
end_time=datetime(2024, 5, 10, 11, 0),
gap_end_time=datetime(2024, 5, 10, 11, 15),
)
Source code in src/codex_services/booking/slot_master/dto.py
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | |
BookingChainSolution
Bases: BaseDTO
One complete solution for the entire request (set of slots for all services).
Found by the engine. Guarantees no conflicts between services and respects all resource availability constraints.
Fields
items (list[SingleServiceSolution]): List of slots in the order of service execution.
score (float): Quality score of the solution (higher is better). Can be influenced by preferred resources, idle time, or resource reuse.
Example
solution = BookingChainSolution(items=[slot1, slot2], score=10.0)
print(f"Booking span: {solution.span_minutes} minutes")
Source code in src/codex_services/booking/slot_master/dto.py
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 | |
Attributes
starts_at
property
Return the start time of the first service in the chain.
ends_at
property
Return the end time of the last service (excluding gap).
span_minutes
property
Return total time from the start of the first to the end of the last service.
Functions
to_display()
Convert the solution into a dictionary for UI/serialization.
Returns:
| Name | Type | Description |
|---|---|---|
Dict |
dict[str, Any]
|
{service_id: {resource_id, start, end}, ...} |
Source code in src/codex_services/booking/slot_master/dto.py
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | |
EngineResult
Bases: BaseDTO
Engine work result containing all discovered solutions.
Fields
mode (BookingMode): The search strategy used. solutions (list[BookingChainSolution]): Found valid schedule options.
Example
result = ChainFinder().find(request, availability)
if result.has_solutions:
print(f"Best start: {result.best.starts_at}")
Source code in src/codex_services/booking/slot_master/dto.py
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 | |
Attributes
has_solutions
property
Return True if at least one solution was found.
best
property
Return the primary solution. - Without scorer: earliest by start time. - After scoring: the option with the highest score.
best_scored
property
Return the option with the maximum score among all solutions. Differs from 'best' if the solution list hasn't been sorted yet.
Functions
get_unique_start_times()
Return unique start times of the first service for UI grid display.
Returns:
| Type | Description |
|---|---|
list[str]
|
List[str]: ["09:00", "09:30", ...] |
Source code in src/codex_services/booking/slot_master/dto.py
366 367 368 369 370 371 372 373 374 | |
WaitlistEntry
Bases: BaseDTO
Notification data for a nearest available slot for waitlisted clients.
Used when a desired slot was unavailable, but an alternative was found (e.g., via find_nearest() or a background worker).
Fields
available_date (date): Date of the found alternative slot. available_time (str): Start time of the first service ("HH:MM"). solution (BookingChainSolution): Complete schedule details. days_from_request (int): Delta from original request date for ranking.
Example
Worker detects a cancellation:
result = finder.find_nearest(request, search_from=original_date) if result.has_solutions: entry = WaitlistEntry.from_engine_result(result, original_date) notify_client(entry)
Source code in src/codex_services/booking/slot_master/dto.py
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 | |
Functions
from_engine_result(result, original_date)
classmethod
Factory method to create a WaitlistEntry from an EngineResult.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
EngineResult
|
The engine's output. |
required |
original_date
|
date
|
Original requested date for delta calculation. |
required |
Returns:
| Type | Description |
|---|---|
WaitlistEntry | None
|
WaitlistEntry or None if no solutions exist. |
Source code in src/codex_services/booking/slot_master/dto.py
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 | |