Modelo de Dominio: Scheduling (Reservas)¶
Proposito¶
Modelo de dominio completo del bounded context de Scheduling. Este es el contexto core del sistema: gestiona la disponibilidad de medicos y la reserva de turnos.
Metadata¶
| Campo | Valor |
|---|---|
| Bounded Context | Scheduling |
| Domain Expert | Laura Martinez (Product Owner) |
| Autor tecnico | Carlos Ramirez |
| Fecha | 2025-03-25 |
| Estado | Validated |
1. Descripcion del Contexto¶
El contexto de Scheduling es responsable de gestionar la disponibilidad de medicos y permitir a pacientes reservar, cancelar, y consultar turnos. Es el corazon del sistema: sin Scheduling no hay producto.
NO es responsabilidad de Scheduling: la autenticacion (Identity), la gestion de clinicas (Clinic Management), ni el envio de notificaciones (Notification). Scheduling emite eventos que otros contextos consumen.
2. Entidades (Entities)¶
Booking (Turno)¶
Identidad: UUID autogenerado al momento de la reserva.
Atributos clave: | Atributo | Tipo | Descripcion | |----------|------|-------------| | id | UUID | Identificador unico del turno | | patientId | UUID | Referencia al paciente (del contexto Identity) | | doctorId | UUID | Referencia al medico | | clinicId | UUID | Referencia a la clinica | | specialtyId | UUID | Especialidad de la consulta | | date | Date | Fecha del turno | | timeRange | TimeRange (VO) | Hora inicio y fin | | status | BookingStatus (VO) | Estado actual del turno | | cancellationPenalty | boolean | Si la cancelacion genero penalizacion |
Invariantes: - Un booking siempre tiene paciente, medico, clinica, y especialidad. - La fecha del booking debe ser futura al momento de la creacion. - El timeRange debe estar dentro de la disponibilidad del medico. - Solo se puede cancelar un booking con status CONFIRMED. - Un booking completado o no-show no puede cambiar de estado.
Ciclo de vida:
CONFIRMED -> CANCELLED (por paciente o medico)
CONFIRMED -> COMPLETED (medico marca atencion realizada)
CONFIRMED -> NO_SHOW (medico marca que el paciente no vino)
DoctorAvailability (Disponibilidad del Medico)¶
Identidad: UUID.
Atributos clave: | Atributo | Tipo | Descripcion | |----------|------|-------------| | id | UUID | Identificador unico | | doctorId | UUID | Medico al que pertenece | | clinicId | UUID | Clinica donde atiende en este horario | | dayOfWeek | DayOfWeek (VO) | Dia de la semana (0-6) | | timeRange | TimeRange (VO) | Hora inicio y fin de atencion | | slotDurationMinutes | integer | Duracion de cada slot |
Invariantes: - Un medico no puede tener dos disponibilidades que se solapen en el mismo dia y clinica. - Un medico no puede tener disponibilidades en dos clinicas diferentes que se solapen en horario. - La duracion del slot debe ser 15, 20, 30, 45, o 60 minutos. - El timeRange debe ser de al menos un slot de duracion.
BlockedDate (Dia Bloqueado)¶
Identidad: UUID.
Atributos clave: | Atributo | Tipo | Descripcion | |----------|------|-------------| | id | UUID | Identificador unico | | doctorId | UUID | Medico | | date | Date | Dia bloqueado | | reason | string (opcional) | Motivo del bloqueo |
Invariantes: - La fecha debe ser futura. - No puede haber dos blocked dates para el mismo medico y fecha.
3. Value Objects¶
TimeRange (Rango Horario)¶
Atributos: | Atributo | Tipo | Validacion | |----------|------|------------| | startTime | Time | HH:mm, debe ser < endTime | | endTime | Time | HH:mm, debe ser > startTime |
Reglas de creacion: - startTime debe ser anterior a endTime. - La diferencia minima es 15 minutos. - Se expresan en la zona horaria de la clinica.
BookingStatus¶
Valores posibles: CONFIRMED, CANCELLED, COMPLETED, NO_SHOW
Transiciones validas:
- CONFIRMED -> CANCELLED | COMPLETED | NO_SHOW
- Los demas son estados finales.
DayOfWeek¶
Valores: 0 (Domingo) a 6 (Sabado)
TimeSlot (Slot Disponible - Calculado)¶
Atributos: | Atributo | Tipo | Validacion | |----------|------|------------| | date | Date | Fecha del slot | | timeRange | TimeRange | Horario del slot | | doctorId | UUID | Medico | | clinicId | UUID | Clinica | | isAvailable | boolean | Si esta libre o no |
Nota: TimeSlot NO se persiste en la BD. Se calcula on-the-fly a partir de DoctorAvailability - BlockedDates - Bookings existentes.
4. Aggregates¶
Booking Aggregate¶
Aggregate Root: Booking
Componentes: - Booking (entidad raiz) - TimeRange (value object) - BookingStatus (value object)
Invariantes del aggregate: - Un booking solo puede crearse si el slot esta disponible. - La cancelacion con < 24h genera penalizacion automaticamente. - Solo el paciente dueno o el medico asignado pueden cancelar.
Operaciones:
- create(patientId, doctorId, clinicId, specialtyId, date, timeRange) -> BookingConfirmed event
- cancel(cancelledBy, reason) -> BookingCancelled event
- complete() -> BookingCompleted event
- markNoShow() -> PatientNoShow event
DoctorSchedule Aggregate¶
Aggregate Root: Doctor (referencia, la entidad vive en Clinic Management)
Componentes: - DoctorAvailability[] (entidades) - BlockedDate[] (entidades) - TimeRange (value object) - DayOfWeek (value object)
Invariantes del aggregate: - Las disponibilidades no pueden solaparse. - Bloquear un dia no cancela bookings existentes (se notifica al paciente).
Operaciones:
- addAvailability(clinicId, dayOfWeek, timeRange, slotDuration)
- removeAvailability(availabilityId)
- blockDate(date, reason) -> DateBlocked event
- unblockDate(date)
5. Domain Events¶
| Evento | Trigger | Datos | Consumidores |
|---|---|---|---|
| BookingConfirmed | Paciente reserva un turno | bookingId, patientId, doctorId, clinicId, date, timeRange | Notification (email confirmacion) |
| BookingCancelled | Paciente o medico cancela | bookingId, cancelledBy, reason, hasPenalty | Notification (email cancelacion) |
| BookingCompleted | Medico marca turno como completado | bookingId, doctorId, patientId | Analytics (futuro) |
| PatientNoShow | Medico marca no-show | bookingId, patientId | Notification (email), Penalization logic |
| DateBlocked | Medico bloquea un dia | doctorId, date, affectedBookings[] | Notification (avisar pacientes afectados) |
6. Domain Services¶
AvailabilityCalculator¶
Responsabilidad: Calcular los slots disponibles de un medico en un rango de fechas.
Inputs: - doctorId, dateFrom, dateTo
Output: - Lista de TimeSlot con isAvailable = true
Reglas de negocio que implementa: - Genera slots a partir de DoctorAvailability (horario recurrente). - Resta los BlockedDates (dias completos bloqueados). - Resta los Bookings existentes con status CONFIRMED. - Filtra slots pasados (no muestra slots cuya hora ya paso). - Aplica la ventana de reserva (minimo 2h antes, maximo 30 dias adelante).
BookingConflictValidator¶
Responsabilidad: Verificar que un slot no este ocupado antes de crear un booking.
Inputs: - doctorId, date, timeRange
Output: - boolean (true si hay conflicto)
Reglas de negocio que implementa:
- Verifica que no exista un booking CONFIRMED para el mismo medico, fecha, y timeRange.
- Usa bloqueo pesimista (SELECT FOR UPDATE) para evitar race conditions.
PenalizationService¶
Responsabilidad: Gestionar las penalizaciones por cancelacion tardia.
Inputs: - patientId, bookingDate, cancellationTime
Output: - boolean (si aplica penalizacion), penaltyCount (total de penalizaciones activas)
Reglas de negocio que implementa: - Penalizacion si cancela con < 24h de anticipacion. - Bloqueo de 30 dias si acumula 3 penalizaciones. - Las penalizaciones se resetean despues de 6 meses sin nuevas.
7. Relaciones con Otros Contextos¶
| Otro Contexto | Tipo de Relacion | Que se comparte |
|---|---|---|
| Identity & Access | Customer/Supplier | Scheduling consume User ID del JWT. No sabe nada del password o session. |
| Clinic Management | Customer/Supplier | Scheduling consume Doctor ID, Clinic ID, Specialty ID. Puede consultar nombre del medico para mostrar en la UI. |
| Notification | Publisher/Subscriber | Scheduling publica domain events. Notification los consume y envia emails. Scheduling no sabe ni le importa como se envia el email. |
Checklist de Completitud¶
- Entidades identificadas con invariantes
- Value objects definidos con reglas de validacion
- Aggregates delimitados (un aggregate por transaccion)
- Domain events listados con consumidores
- Domain services con reglas de negocio
- Validado con domain expert (Laura Martinez)
- Revisada por otro ingeniero
Archivos relacionados¶
- ubiquitous-language.md - Lenguaje del dominio
- bounded-contexts.md - Mapa de contextos
- _template.domain.md - Plantilla
- ../01-specs/feature-booking-system.spec.md - Spec de reservas
- ../04-api-contracts/api-bookings.md - API de reservas
- ../05-testing-strategy/bdd-scenarios-booking.md - Escenarios BDD