Skip to main content

Overview

The MesaRepositorio defines the contract for table management operations, including CRUD operations, zone management, and intelligent table availability search. The Firestore implementation (MesaRepositorioFirestore) integrates with ReservaRepositorio to check table availability.

Interface

lib/dominio/repositorios/mesa_repositorio.dart
abstract class MesaRepositorio {
  Future<List<Mesa>> obtenerMesas();
  Future<Mesa?> obtenerMesaPorId(String mesaId);
  Future<List<Mesa>> obtenerMesasPorNegocio(String negocioId);
  Future<Mesa?> agregarMesa(Mesa mesa);
  Future<bool> actualizarMesa(Mesa mesa);
  Future<bool> eliminarMesa(String mesaId);
  
  Future<List<String>> obtenerZonasDisponibles(String negocioId);
  
  Future<Mesa?> buscarMesaDisponibleEnZona({
    required String zona,
    required DateTime fecha,
    required DateTime hora,
    required int numeroPersonas,
    required String negocioId,
  });
}

Methods

obtenerMesas

Retrieves all tables from all restaurants, ordered by name.
Future<List<Mesa>>
List<Mesa>
Returns a list of all tables sorted alphabetically by name. Returns an empty list if there’s an error.
Example Usage
final todasLasMesas = await repositorio.obtenerMesas();
print('Total de mesas en el sistema: ${todasLasMesas.length}');

obtenerMesaPorId

Retrieves a specific table by its unique identifier.
mesaId
String
required
The unique identifier of the table.
Future<Mesa?>
Mesa?
Returns the table if found, or null if it doesn’t exist or there’s an error.
Example Usage
final mesa = await repositorio.obtenerMesaPorId('mesa_123');
if (mesa != null) {
  print('Mesa ${mesa.nombre}: capacidad ${mesa.capacidad}');
}

obtenerMesasPorNegocio

Retrieves all tables belonging to a specific restaurant.
negocioId
String
required
The unique identifier of the restaurant.
Future<List<Mesa>>
List<Mesa>
Returns all tables for the restaurant, sorted by name. Returns an empty list if none found or error occurs.
Implementation Details:
  • Uses Firestore where clause on negocioId field
  • Sorts results in memory to avoid requiring composite indexes
  • Includes debug logging for troubleshooting
Example Usage
final mesasRestaurante = await repositorio.obtenerMesasPorNegocio('negocio_abc');
print('El restaurante tiene ${mesasRestaurante.length} mesas');

for (final mesa in mesasRestaurante) {
  print('${mesa.nombre} (${mesa.zona}): ${mesa.capacidad} personas');
}

agregarMesa

Adds a new table to the system.
mesa
Mesa
required
The table object to create. The ID will be auto-generated by Firestore.
Future<Mesa?>
Mesa?
Returns the created table with its assigned ID, or null if the operation fails.
Example Usage
final nuevaMesa = Mesa(
  id: '', // Will be auto-generated
  nombre: 'Mesa 12',
  capacidad: 4,
  negocioId: 'negocio_abc',
  zona: 'Terraza',
);

final mesaCreada = await repositorio.agregarMesa(nuevaMesa);
if (mesaCreada != null) {
  print('Mesa creada con ID: ${mesaCreada.id}');
}

actualizarMesa

Updates an existing table’s information.
mesa
Mesa
required
The table object with updated information. Must include a valid ID.
Future<bool>
bool
Returns true if the update was successful, false otherwise.
Example Usage
final mesa = await repositorio.obtenerMesaPorId('mesa_123');
if (mesa != null) {
  final mesaActualizada = mesa.copyWith(capacidad: 6);
  final exitoso = await repositorio.actualizarMesa(mesaActualizada);
  
  if (exitoso) {
    print('Mesa actualizada correctamente');
  }
}

eliminarMesa

Deletes a table from the system.
mesaId
String
required
The ID of the table to delete.
Future<bool>
bool
Returns true if the deletion was successful, false otherwise.
This is a hard delete operation. Consider checking for active reservations before deleting a table.
Example Usage
final exitoso = await repositorio.eliminarMesa('mesa_123');
if (exitoso) {
  print('Mesa eliminada correctamente');
}

obtenerZonasDisponibles

Retrieves all unique zone names used in a restaurant’s tables.
negocioId
String
required
The unique identifier of the restaurant.
Future<List<String>>
List<String>
Returns a list of unique zone names (e.g., [“Salón”, “Terraza”, “VIP”]). Returns an empty list on error.
Implementation Details:
  • Fetches all tables for the restaurant
  • Extracts unique zone values using a Set
  • Useful for populating UI dropdowns and zone selectors
Example Usage
final zonas = await repositorio.obtenerZonasDisponibles('negocio_abc');
print('Zonas disponibles:');
for (final zona in zonas) {
  print('- $zona');
}

buscarMesaDisponibleEnZona

Intelligently searches for the best available table in a specific zone that can accommodate a group.
zona
String
required
The zone name to search in (e.g., “Salón”, “Terraza”).
fecha
DateTime
required
The date of the reservation.
hora
DateTime
required
The start time of the reservation.
numeroPersonas
int
required
The number of guests to accommodate.
negocioId
String
required
The restaurant’s unique identifier.
Future<Mesa?>
Mesa?
Returns the best available table, or null if no suitable table is found.
Algorithm:
  1. Fetches all tables for the restaurant
  2. Filters tables by:
    • Matching zone name
    • Can accommodate the group (using Mesa.puedeAcomodar() method)
  3. Sorts by capacity (ascending) to find the best-fitting table
  4. Iterates through sorted tables, checking availability via ReservaRepositorio.mesaDisponible()
  5. Returns the first available table found
Best-Fit Logic:
  • Prioritizes tables closest in size to the group
  • Avoids wasting large tables on small groups
  • Uses a fixed 60-minute duration for availability checking
Example Usage
final mejorMesa = await repositorio.buscarMesaDisponibleEnZona(
  zona: 'Terraza',
  fecha: DateTime(2026, 3, 15),
  hora: DateTime(2026, 3, 15, 20, 0),
  numeroPersonas: 4,
  negocioId: 'negocio_abc',
);

if (mejorMesa != null) {
  print('Mesa disponible: ${mejorMesa.nombre} (capacidad: ${mejorMesa.capacidad})');
} else {
  print('No hay mesas disponibles en la Terraza para esa hora');
}

Firestore Implementation

Collection Structure

Tables are stored in the mesas collection:
Firestore Document
{
  "nombre": "Mesa 12",
  "capacidad": 4,
  "negocioId": "negocio_abc",
  "zona": "Terraza"
}

Zone Migration

The implementation includes automatic migration logic for legacy zone enum values:
Legacy EnumMigrated Value
"terraza""Terraza"
"salon""Salón"
"jardin""Jardín"
"barrabar""Barra/Bar"

Constructor Dependencies

MesaRepositorioFirestore({
  required ReservaRepositorio reservaRepositorio
})
The repository requires a ReservaRepositorio instance to check table availability.

Mesa Entity

class Mesa {
  final String id;
  final String nombre;
  final int capacidad;
  final String negocioId;
  final String zona;
  
  /// Checks if the table can accommodate a group
  /// - Must have capacity >= numeroPersonas
  /// - Must not have more than 3 extra seats (avoid wasting large tables)
  bool puedeAcomodar(int numeroPersonas) {
    if (capacidad < numeroPersonas) return false;
    if (capacidad > numeroPersonas + 3) return false;
    return true;
  }
}
Capacity Logic:
  • A table with capacity 4 can accommodate: 1, 2, 3, 4, 5, 6, 7 people
  • A table with capacity 4 cannot accommodate: 8+ people (too small) or 0 people (invalid)
  • This prevents assigning 10-person tables to 2-person groups

See Also

Build docs developers (and LLMs) love