Skip to main content
The Habitacion entity represents a hotel room with state management capabilities. It maintains a complete history of state changes through the HabitacionHistorial pattern, enabling tracking of availability, occupancy, maintenance, and cleaning states.

Overview

Habitacion is a sealed entity that manages room information and maintains an immutable history of state transitions. The current state is determined by the latest open history record. Namespace: SGRH.Domain.Entities.Habitaciones Source: ~/workspace/source/SGRH.Domain/Entities/Habitaciones/Habitacion.cs

Properties

HabitacionId
int
required
Unique identifier for the room (primary key).
CategoriaHabitacionId
int
required
Reference to the room category (determines capacity, pricing, amenities).
NumeroHabitacion
int
required
Room number (must be > 0).
Piso
int
required
Floor number where the room is located (must be > 0).
Historial
IReadOnlyCollection<HabitacionHistorial>
required
Read-only collection of all state change records. Modifications only through CambiarEstado().
EstadoActual
HabitacionHistorial?
Calculated property: Returns the current active state record (where FechaFin is null).
EstadoActual => _historial.FirstOrDefault(h => h.FechaFin is null)

Constructor

public Habitacion(int categoriaHabitacionId, int numeroHabitacion, int piso)
Creates a new room with initial Disponible state.

Parameters

  • categoriaHabitacionId: Valid category ID (must be > 0)
  • numeroHabitacion: Room number (must be > 0)
  • piso: Floor number (must be > 0)

Initial State

Automatically creates a history record with:
  • EstadoHabitacion = Disponible
  • FechaInicio = DateTime.UtcNow
  • FechaFin = null (open/active)
  • MotivoCambio = null

Example

var habitacion = new Habitacion(
    categoriaHabitacionId: 3, // Suite
    numeroHabitacion: 301,
    piso: 3
);

Room States

EstadoHabitacion Enum

public enum EstadoHabitacion
{
    Disponible,      // Available for reservation
    Ocupada,         // Currently occupied
    Mantenimiento,   // Under maintenance
    Limpieza         // Being cleaned
}

State Transition Rules

Available for Reservation
  • Room is ready for guests
  • Can be reserved
  • No motivo required
  • Cannot have a motivo specified
Currently Occupied
  • Guest is checked in
  • Cannot be reserved (except by current reservation)
  • No motivo required
  • Cannot have a motivo specified
Under Maintenance
  • Room needs repairs or upgrades
  • Cannot be reserved
  • Motivo REQUIRED: Must specify reason for maintenance
  • Prevents reservations during maintenance period
Being Cleaned
  • Room is being prepared
  • Cannot be reserved
  • Motivo REQUIRED: Must specify cleaning reason/type
  • Temporary state before returning to Disponible

Methods

CambiarEstado

public void CambiarEstado(EstadoHabitacion nuevoEstado, string? motivo = null)
Changes the room state with proper history tracking. Process:
  1. Validates the new state is different from current
  2. Closes the current history record (FechaFin = DateTime.UtcNow)
  3. Creates a new open history record with the new state
Parameters:
  • nuevoEstado: Target state
  • motivo: Required for Mantenimiento and Limpieza, forbidden for others
Examples:
habitacion.CambiarEstado(
    EstadoHabitacion.Mantenimiento,
    "Reparación de aire acondicionado"
);
Throws:
  • BusinessRuleViolationException if already in the target state
  • ValidationException if motivo rules are violated (see HabitacionHistorial)

CambiarCategoria

public void CambiarCategoria(int nuevaCategoriaId)
Updates the room category (e.g., upgrade from Standard to Suite). Parameters:
  • nuevaCategoriaId: Valid category ID (must be > 0)
Example:
habitacion.CambiarCategoria(nuevaCategoriaId: 5); // Upgrade to Deluxe
Category changes affect future pricing but do not modify existing reservations.

HabitacionHistorial

Each state change creates a history record:
public sealed class HabitacionHistorial
{
    public int HabitacionHistorialId { get; private set; }
    public int HabitacionId { get; private set; }
    public EstadoHabitacion EstadoHabitacion { get; private set; }
    public DateTime FechaInicio { get; private set; }
    public DateTime? FechaFin { get; private set; }
    public string? MotivoCambio { get; private set; }
}

History Record Lifecycle

  1. Created: FechaInicio = DateTime.UtcNow, FechaFin = null (open)
  2. Active: The current state (only one record has FechaFin = null)
  3. Closed: When state changes, FechaFin = DateTime.UtcNow

Motivo Validation Rules

Implemented in HabitacionHistorial constructor:
if (estado is EstadoHabitacion.Mantenimiento or EstadoHabitacion.Limpieza)
{
    if (string.IsNullOrWhiteSpace(motivo))
        throw new ValidationException(
            $"El estado {estado} requiere un motivo de cambio.");
}
else
{
    if (!string.IsNullOrWhiteSpace(motivo))
        throw new ValidationException(
            $"El estado {estado} no debe tener motivo de cambio.");
}
Maximum length: 255 characters

Business Rules

  • Cannot transition to the same state (throws BusinessRuleViolationException)
  • Each state change must follow motivo rules
  • All state changes are tracked with timestamps
  • Current state is always the record with FechaFin = null
  • History cannot be modified directly from outside the entity
  • Only CambiarEstado() can add history records
  • Closed records cannot be reopened (enforced by HabitacionHistorial.Cerrar())
Rooms in Mantenimiento state cannot be reserved. The reservation policy (IReservaDomainPolicy.EnsureHabitacionNoEnMantenimiento) validates this at the application layer.

Usage Patterns

Checking Current State

var estado = habitacion.EstadoActual?.EstadoHabitacion;

if (estado == EstadoHabitacion.Disponible)
{
    // Room can be reserved
}

State History Audit

foreach (var historial in habitacion.Historial.OrderByDescending(h => h.FechaInicio))
{
    Console.WriteLine($"{historial.EstadoHabitacion}: {historial.FechaInicio} - {historial.FechaFin}");
    if (!string.IsNullOrEmpty(historial.MotivoCambio))
        Console.WriteLine($"  Motivo: {historial.MotivoCambio}");
}

Typical Workflow

// 1. Guest checks in
habitacion.CambiarEstado(EstadoHabitacion.Ocupada);

// 2. Guest checks out, cleaning needed
habitacion.CambiarEstado(EstadoHabitacion.Limpieza, "Limpieza estándar");

// 3. Cleaning complete
habitacion.CambiarEstado(EstadoHabitacion.Disponible);

// 4. Maintenance issue found
habitacion.CambiarEstado(EstadoHabitacion.Mantenimiento, "Tubería con fuga");

// 5. Maintenance complete, needs cleaning
habitacion.CambiarEstado(EstadoHabitacion.Limpieza, "Limpieza post-reparación");

// 6. Ready for next guest
habitacion.CambiarEstado(EstadoHabitacion.Disponible);
  • CategoriaHabitacion: Defines room type, capacity, and base pricing
  • TarifaTemporada: Pricing per category per season (see TarifaTemporada)
  • Reserva: References rooms through DetalleReserva (see Reserva)

Build docs developers (and LLMs) love