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
- Registration -- Owner submits restaurant details via Smackz-Admin
- Pending Approval -- SuperAdmin reviews the application
- Approved -- Firebase project is created, image storage is provisioned
- 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 definitionyum/api/schema/restaurant.ts-- Zod schemasyum/api/services/restaurantService.ts-- Business logicdocs/Multi-Location-Restaurant-Support-FRD.md-- Multi-location FRDdocs/Food-Truck-Location-Support.md-- Food truck location support