Restaurant Table Booking on Website

Our company is engaged in the development, support and maintenance of sites of any complexity. From simple one-page sites to large-scale cluster systems built on micro services. Experience of developers is confirmed by certificates from vendors.

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Showing 1 of 1 servicesAll 2065 services
Restaurant Table Booking on Website
Medium
~5 business days
FAQ

Our competencies:

Development stages

Latest works

  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1262
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    874
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    851

Implementing Restaurant Table Booking on a Website

Table booking is a task with several non-trivial details: table capacity must match guest count, restaurant operates in shifts (lunch/dinner), and overbooking is sometimes desired behavior.

Hall and Table Model

CREATE TABLE restaurant_halls (
    id          SERIAL PRIMARY KEY,
    name        VARCHAR(100),   -- 'Main Hall', 'Terrace', 'VIP'
    is_active   BOOLEAN DEFAULT TRUE
);

CREATE TABLE restaurant_tables (
    id              SERIAL PRIMARY KEY,
    hall_id         INTEGER REFERENCES restaurant_halls(id),
    table_number    VARCHAR(10),
    min_guests      SMALLINT DEFAULT 1,
    max_guests      SMALLINT NOT NULL,
    is_combinable   BOOLEAN DEFAULT FALSE,  -- can move adjacent
    is_active       BOOLEAN DEFAULT TRUE
);

CREATE TABLE table_bookings (
    id              BIGSERIAL PRIMARY KEY,
    table_id        INTEGER REFERENCES restaurant_tables(id),
    guest_name      VARCHAR(255) NOT NULL,
    guest_phone     VARCHAR(50) NOT NULL,
    guest_email     VARCHAR(255),
    guests_count    SMALLINT NOT NULL,
    starts_at       TIMESTAMP NOT NULL,
    ends_at         TIMESTAMP NOT NULL,
    status          VARCHAR(20) DEFAULT 'pending',
    special_wishes  TEXT,
    deposit_paid    BOOLEAN DEFAULT FALSE,
    deposit_amount  NUMERIC(10,2),
    source          VARCHAR(30) DEFAULT 'website',  -- 'website','phone','walkin'
    created_at      TIMESTAMP DEFAULT NOW()
);

Shifts and Time Slots

Restaurant doesn't book a table "at 15:37" — only for a shift or fixed slot:

SHIFTS = {
    'lunch': {'start': time(12, 0), 'end': time(15, 0), 'duration': timedelta(hours=2)},
    'dinner': {'start': time(18, 0), 'end': time(23, 0), 'duration': timedelta(hours=2)},
}

def get_booking_slots(date: date) -> list[dict]:
    slots = []
    for shift_name, shift in SHIFTS.items():
        current = datetime.combine(date, shift['start'])
        end_dt = datetime.combine(date, shift['end'])
        while current + shift['duration'] <= end_dt:
            slots.append({
                'shift': shift_name,
                'starts_at': current,
                'ends_at': current + shift['duration'],
            })
            current += timedelta(hours=1)  # slots every hour
    return slots

Finding Table by Guest Count

def find_available_table(guests: int, starts_at: datetime, ends_at: datetime, hall_id: int = None):
    query = """
        SELECT t.*
        FROM restaurant_tables t
        WHERE t.min_guests <= %(guests)s
          AND t.max_guests >= %(guests)s
          AND t.is_active = TRUE
          AND (%(hall_id)s IS NULL OR t.hall_id = %(hall_id)s)
          AND t.id NOT IN (
            SELECT table_id FROM table_bookings
            WHERE status NOT IN ('cancelled', 'no_show')
              AND tsrange(starts_at, ends_at, '[)') && tsrange(%(starts)s, %(ends)s, '[)')
          )
        ORDER BY t.max_guests ASC   -- select smallest suitable table
        LIMIT 1
    """
    return db.fetchone(query, {
        'guests': guests, 'hall_id': hall_id,
        'starts': starts_at, 'ends': ends_at,
    })

Combining Tables

If there's no 8-person table but two adjacent 4-person tables exist — can suggest combining. Requires an adjacency table:

CREATE TABLE table_adjacency (
    table_a INTEGER REFERENCES restaurant_tables(id),
    table_b INTEGER REFERENCES restaurant_tables(id),
    PRIMARY KEY (table_a, table_b)
);

Confirmation and Reminders

Time Action
Immediately SMS/email to client with booking details
24 hours before SMS reminder
2 hours before SMS "We're waiting for you at 19:00"
+30 min after start If no-show — change status to no_show, release table
+1 day Email requesting review

Optional deposit when booking — payment gateway integration. Deposit is charged if guest doesn't show and hasn't cancelled N hours before.

Implementation Timeline

Basic system with one hall, shifts and SMS/email notifications — 6–8 business days. Multiple halls, table combining, deposits, CMS management, booking history — 10–13 business days.