Skip to content

Restaurants & Locations

The restaurant domain is the core entity in SMACKZ. Every other domain (menus, orders, pages, loyalty) is scoped to a restaurant.

Restaurant Lifecycle

Registration -> Pending Approval -> Approved -> Active
                                             \-> Rejected
  1. Registration -- Owner submits restaurant details via Smackz-Admin
  2. Pending Approval -- SuperAdmin reviews the application
  3. Approved -- Firebase project is created, image storage is provisioned
  4. Active -- Restaurant is live and accepting orders

On approval, the system automatically:

  • Creates a Firebase project for the restaurant (multi-tenant auth)
  • Provisions image storage folders on Cloudflare R2
  • Sets up default configuration entries

Restaurant Data

Key fields stored in the restaurant table:

Category Fields
Identity name, slug, description, cuisines
Contact email, phone, address, coordinates
Branding logo, images, theme configuration
Operations working hours, timezone, delivery radius
Config Firebase project ID, payment settings, delivery provider
Social website, Instagram, Facebook, Twitter links

Many of these are stored as JSONB columns (images, cuisines, dining options, socials, parking options), allowing flexible configuration without schema changes.

Working Hours

Each restaurant has per-day working hours with support for multiple time slots:

{
  "workingHours": [
    {
      "workingDay": "Monday",
      "isHoliday": false,
      "workingHours": [
        { "openTime": "09:00 AM", "closeTime": "02:00 PM", "section": "Lunch" },
        { "openTime": "05:00 PM", "closeTime": "11:00 PM", "section": "Dinner" }
      ]
    }
  ]
}

Times use 12-hour format with timezone conversion (see Menus for timezone handling).

Multi-Location Support

Restaurants can have multiple locations, each with its own:

  • Address and coordinates
  • Working hours
  • Delivery radius
  • Active/inactive status
  • Dining options, parking options, delivery provider, working days, holidays, token counters

Locations are stored in the locations table, referenced by restaurant_id. The lakehouse also tracks location data for analytics.

Location-Scoped Settings (2026-04)

In April 2026, several per-branch settings were migrated from restaurants to locations. The canonical rule: if a feature has its own table, it gets a NOT NULL locationId column; if a feature was a column on restaurants, it has been moved to locations. Every row now belongs to exactly one location — there is no "location row OR restaurant-level fallback" pattern anywhere in the codebase.

What Moved

Setting Old New Shape
Dining options restaurants.diningOptions (jsonb) locations.diningOptions (jsonb) { dineIn, pickup, delivery }
Parking options restaurants.parkingOptions (jsonb) locations.parkingOptions (jsonb) { noParking, onPremise, parkingLot }
Delivery provider restaurants.deliveryProvider (text) locations.deliveryProvider (text) doordash \| uber_eats \| grubhub \| postmates \| self
Working days restaurant_working_days (nullable locationId) restaurant_working_days (NOT NULL locationId) unchanged row shape
Holidays restaurant_holidays (no locationId) restaurant_holidays (NOT NULL locationId) unchanged
Token counters token_number (no locationId) token_number (NOT NULL locationId) unchanged

restaurants.taxRate was deleted. Taxes are now computed exclusively from the tax_rates table, which has a locationIds JSONB column for per-location assignment. The legacy takeAway alias on diningOptions was also dropped — pickup is canonical.

Routes Changed

  • Restaurant-level working-hours / holidays endpoints were removed.
  • New location-scoped equivalents: /restaurants/:restaurantId/locations/:locationId/working-hours, /restaurants/:restaurantId/locations/:locationId/holidays[/:holidayId], etc.
  • New locations auto-seed working hours/holidays from a default location or sensible defaults (Mon–Fri 9–5).

See yum/docs/LOCATION_SCOPED_SETTINGS.md for the canonical reference and yum/docs/ROUTE_LOCATION_AUDIT.md for the policy on which routes carry locationId (only list/query — CRUD-by-ID does not).

Firebase Configuration

Each restaurant can have its own Firebase project for isolated user authentication:

  • Platform Firebase -- Used by SuperAdmin and as fallback
  • Restaurant Firebase -- Isolated user pool per restaurant
  • Configuration managed via CLI (npm run manage:firebase) or API endpoints

Dynamic Pages

Restaurants have configurable pages (homepage, about, terms, privacy, support) built from ordered sections. See Page Renderer for details.

Key Endpoints

Endpoint Method Description
/restaurants POST Register new restaurant
/restaurants GET List restaurants (admin)
/restaurants/{id} GET/PUT Restaurant details
/restaurants/{id}/working-hours GET/PUT Operating hours
/restaurants/{id}/firebase-config GET/PUT/DELETE Firebase settings (admin)
/restaurants/{id}/pages GET/POST Dynamic pages

Key Files

  • yum/api/db/models/restaurant.ts -- Restaurant table definition
  • yum/api/schema/restaurant.ts -- Zod schemas
  • yum/api/services/restaurantService.ts -- Business logic
  • docs/Multi-Location-Restaurant-Support-FRD.md -- Multi-location FRD
  • docs/Food-Truck-Location-Support.md -- Food truck location support