π½οΈ Lucky Restaurant/Business Management System
Full-Featured, Optimized & Dynamic Restaurant/Business Management System for FiveM
A production-ready, Lua-based restaurant and business management framework built for FiveM servers. Designed with lazy-loading architecture, RAM-first caching, framework-agnostic bridge system, and complete ox_lib integration for a premium roleplay experience.
π Table of Contents
- Features
- Architecture Overview
- Dependencies
- Installation
- Database Setup
- Configuration
- Admin Setup Guide
- System Modules
- Exports Reference
- Bridge System
- Localization
- Permission System
- FAQ & Troubleshooting
β¨ Features
Core Systems
- πͺ Multi-Restaurant Support β Unlimited restaurants, each with independent menus, recipes, orders, and settings
- π¦ Lazy Loading Architecture β Restaurants load from SQL on first access, keeping memory usage minimal
- β‘ RAM-First Caching β All runtime data cached in memory with instant SQL sync on every mutation
- π Job Grade Permission System β Granular access control based on
qbx_core/qb-core/ESXjob grades
Business Operations
- π Dynamic Menu Management β Add, edit, remove menu items with categories and pricing in real-time
- π§βπ³ Kitchen Station System β Cooking stations (Grill, Fryer, Oven, Coffee Machine) and Assembly stations (Prep Table, Drink Station)
- π³ Dynamic Recipe System β Create restaurant-specific recipes with custom ingredients, linked to menu items
- π Cart & Order System β Full customer ordering flow with FIFO queue, status tracking, and real-time kitchen updates
- π° Payment System β Cash and bank card payments with customer confirmation flow
- π§Ύ Receipt System β Physical receipt items (ox_inventory) with metadata, single/bulk redemption at NPC
- π² Tip System β Configurable tip percentages (0-20%) added during payment
- π·οΈ Discount System β Time-limited hourly discounts targeting all products, categories, or specific items with overlap prevention
- π Z Report System β Revenue analytics: total income, tips, payment method breakdown, discount stats
- πͺ Wholesale Market β NPC-based bulk ingredient purchasing via
ox_inventoryshop system
Technical
- π Multi-Framework Bridge β Supports QBX Core, QB-Core, and ESX out of the box
- π― Multi-Target Bridge β Supports ox_target and qb-target
- π¦ Multi-Inventory Bridge β Supports ox_inventory and qb-inventory
- π Full Localization β ox_lib locale system with EN and TR translations
- ποΈ Repository Pattern β Clean SQL abstraction layer with dedicated repository modules
- π Dynamic Interaction Points β In-game placement system for cashiers, order points, kitchens, storage, and trays
- π§Ή Automatic Cleanup β Timed-out orders, expired discounts, and payment requests auto-cleanup
ποΈ Architecture Overview
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CLIENT SIDE β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β point_manager.lua β ox_lib Points (proximity) β
β interaction_editor.lua β Placement mode UI β
β menu_management.lua β Menu browsing / editing β
β cart_system.lua β Customer cart & ordering β
β cashier_system.lua β Cashier operations β
β kitchen_system.lua β Kitchen station UI β
β management_menu.lua β Manager dashboard β
β receipt_npc.lua β Receipt redemption NPC β
β stock_market.lua β Wholesale NPC interaction β
β admin_menu.lua β Admin restaurant setup β
β npc_manager.lua β Common NPC spawn utility β
βββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββ
β ox_lib callbacks / net events
βββββββββββββββΌββββββββββββββββββββββββββββββββββββββββ
β SERVER SIDE β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β instance_manager.lua β Core: lazy load, RAM cache β
β settings_manager.lua β Settings & interaction pts β
β menu_manager.lua β Menu CRUD + validation β
β order_manager.lua β Order lifecycle & payments β
β recipe_manager.lua β Dynamic recipe CRUD β
β kitchen_manager.lua β Kitchen task engine β
β station_manager.lua β Cooking & assembly logic β
β receipt_manager.lua β Receipt create/redeem β
β discount_manager.lua β Time-limited discounts β
β z_report_manager.lua β Revenue analytics β
β stock_market.lua β Wholesale shop register β
β admin_manager.lua β Admin CRUD operations β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β REPOSITORY LAYER (SQL) β
β base_repository.lua β Query/Insert/Update β
β restaurant_repository.lua β Restaurant CRUD β
β menu_repository.lua β Menu items CRUD β
β recipe_repository.lua β Recipes + ingredients β
β settings_repository.lua β Settings & points I/O β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SHARED LAYER β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β config.lua β Main configuration β
β config_stations.lua β Station definitions β
β bridge/init.lua β Auto-detect framework β
β bridge/core/qb.lua β QBX / QB-Core bridge β
β bridge/core/esx.lua β ESX bridge β
β bridge/inventory/ox.luaβ ox_inventory bridge β
β bridge/inventory/qb.luaβ qb-inventory bridge β
β bridge/target/ox.lua β ox_target bridge β
β bridge/target/qb.lua β qb-target bridge β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββData Flow
- Lazy Loading β Restaurant data loads from MySQL on first
GetRestaurant(jobName)call - RAM Cache β All loaded data lives in
_G.SPC_RestaurantInstancesfor zero-latency access - Instant Sync β Every mutation (menu edit, order create, etc.) writes to SQL first, then updates RAM cache
- Active Orders β Stored only in RAM (never persisted). Completed/cancelled orders log to
lcky_orders_log
Order Lifecycle
created β confirmed β preparing β ready β completed
β β β β
cancelled cancelled cancelled cancelledπ¦ Dependencies
| Dependency | Version | Required |
|---|---|---|
| FiveM Server (opens in a new tab) | Build 5181+ | β |
| ox_lib (opens in a new tab) | Latest | β |
| ox_inventory (opens in a new tab) | Latest | β |
| oxmysql (opens in a new tab) | Latest | β |
| ox_target (opens in a new tab) or qb-target | Latest | β |
| qbx_core (opens in a new tab) or qb-core or ESX | Latest | β |
π Installation
Step 1 β Place the Resource
resources/
βββ [LuckyScripts]/
βββ lcky-restaurant_management/Step 2 β Import the Database
Execute sql/schema.sql in your MySQL database. This creates:
lcky_restaurantsβ Restaurant master tablelcky_menu_itemsβ Menu items per restaurantlcky_recipesβ Dynamic recipeslcky_recipe_ingredientsβ Recipe ingredient mappinglcky_interaction_pointsβ Stored interaction pointslcky_orders_logβ Completed/cancelled order historylcky_discountsβ Time-limited discount records
Step 3 β Register Inventory Items
Add all required items to your ox_inventory items configuration. See the inventoryitems.lua file included in this repository for a complete list of ready-to-use item registration exports.
Step 4 β Add the Resource to Your Server Config
ensure ox_lib
ensure oxmysql
ensure ox_inventory
ensure ox_target
ensure lcky-restaurant_managementStep 5 β Add ACE Permission (Admin)
add_ace group.admin command.restaurantadmin allowStep 6 β Create Restaurants In-Game
Use the /restaurantadmin command to open the admin panel and register your restaurants.
ποΈ Database Setup
The sql/schema.sql file creates all necessary tables with proper indexing and foreign key relationships. All tables use InnoDB with utf8mb4 character set.
Key Tables
| Table | Purpose |
|---|---|
lcky_restaurants | Restaurant definitions (job, name, center coords, radius, settings JSON, open/close times) |
lcky_menu_items | Per-restaurant menu items (label, price, category, base item, recipe link) |
lcky_recipes | Dynamic recipes (assembly station, output item, created by) |
lcky_recipe_ingredients | Recipe ingredients with amounts and sort order |
lcky_interaction_points | Interaction point coordinates and types |
lcky_orders_log | Completed/cancelled order log with payment details, tips, discounts |
lcky_discounts | Time-limited discounts with type, percentage, targets, start/end times |
βοΈ Configuration
Main Config (shared/config.lua)
Permission Grades
Config.Permissions = {
addInteractionPoint = 2, -- Manager+
removeInteractionPoint = 2, -- Manager+
editMenu = 2, -- Manager+
editSettings = 2, -- Manager+
accessStorage = 1, -- Chef+
accessKitchen = 1, -- Chef+
accessCashier = 0, -- All employees
redeemReceipts = 2, -- Manager+
viewZReport = 2, -- Manager+
manageDiscounts = 2, -- Manager+
}Restaurant Definitions
Config.Restaurants = {
["burgershot"] = { name = "Burger Shot", description = "Fast food restaurant" },
["beanmachine"] = { name = "Bean Machine", description = "Coffee shop" },
-- Add more restaurants here
}
Config.RestaurantJobs = { "burgershot", "beanmachine", ... }Default Settings
Config.DefaultSettings = {
isOpen = false, -- Starts closed on every restart
maxMenuItems = 15,
orderTimeout = 1800, -- 30 minutes
maxActiveOrders = 20,
}Menu Categories
Config.MenuCategories = {
burger = { label = "Burgers", icon = "fas fa-burger" },
drink = { label = "Drinks", icon = "fas fa-glass-water" },
dessert = { label = "Desserts", icon = "fas fa-ice-cream" },
pizza = { label = "Pizzas", icon = "fas fa-pizza-slice" },
}Base Food Items
Items selectable as the output item when creating menu entries:
Config.BaseFoodItems = {
"burger", "pizza", "coffee", "donut", "cake_slice",
"sandwich", "taco", "hotdog", "soda", "water", "juice", "icecream"
}Receipt System
Config.ReceiptSystem = {
enabled = true,
itemName = 'receipt',
npc = { model = 's_m_m_linecook', coords = vec4(...), ... },
allowBulkRedeem = true,
maxBulkRedeem = 10,
}Tip, Discount, and Z Report Systems
Config.TipSystem = { enabled = true, maxPercentage = 20, step = 1 }
Config.DiscountSystem = { enabled = true, maxPercentage = 50, maxDurationHours = 6 }
Config.ZReport = { enabled = true, autoArchiveOnClose = false }Station Config (shared/config_stations.lua)
Cooking Stations (Fixed input β output)
| Station | Processes |
|---|---|
| Grill | Raw Meat β Cooked Meat, Raw Bacon β Cooked Bacon, Sausage β Cooked Sausage, Raw Steak β Cooked Steak |
| Fryer | Potato β Fries, Onion β Onion Rings, Raw Chicken β Chicken Nuggets |
| Oven | Dough β Baked Dough, Whole Chicken β Roasted Chicken |
| Coffee Machine | Coffee Beans β Espresso Shot, Milk β Steamed Milk |
Assembly Stations (Dynamic recipe-based)
| Station | Default Recipes |
|---|---|
| Prep Table | Simple Burger, Simple Sandwich, Simple Salad |
| Drink Station | Soda, Fruit Juice |
Assembly Ingredients
The pool of ingredients available when creating custom recipes via the menu editor.
π οΈ Admin Setup Guide
1. Grant Admin Permission
add_ace identifier.fivem:XXXXXX command.restaurantadmin allow2. Create a Restaurant
- Run
/restaurantadminin-game - Select "Add New Restaurant"
- Enter the Core Job Name (must exist in your framework, e.g.,
burgershot) - Enter a Display Name (e.g.,
Burger Shot) - Set a Radius for the proximity area (10-100)
- You'll be placed at the restaurant center β this is saved automatically
3. Add Interaction Points
- As a Manager+ employee, open the Management Menu at the management point
- Go to Interaction Points β Add Point
- Select a type (Cashier, Order, Storage, Tray, Kitchen Station, Kitchen Pass, Management)
- Enter placement mode β walk to desired location, press E to confirm or X to cancel
4. Set Up the Menu
- Open the Management Menu β Edit Menu β Add Item
- Fill in: Name, Description, Price, Category, Base Item
- Optionally create a Custom Recipe by selecting an assembly station and ingredients
- The item appears on the customer order menu immediately
5. Open for Business
- Management Menu β Restaurant Settings β Open Orders
- Customers can now order from Order Points
π System Modules
Instance Manager (Server)
Central module managing restaurant lazy-loading, RAM caching, and data access.
Menu Manager (Server)
Full CRUD for menu items with validation, slug generation, and instant SQL+RAM sync.
Order Manager (Server)
Order lifecycle management. Orders live only in RAM β completed/cancelled orders log to SQL.
Recipe Manager (Server)
Dynamic recipe CRUD per restaurant. Recipes link to menu items and define assembly station, ingredients, and output.
Kitchen Manager (Server)
Kitchen task engine generating pending preparation tasks from active orders.
Station Manager (Server)
Handles cooking (fixed inputβoutput) and assembly (recipe-based) station operations with inventory integration.
Settings Manager (Server)
Manages interaction points, restaurant open/close status, and general settings.
Receipt Manager (Server)
Creates receipt items with metadata and handles single/bulk redemption with money payout.
Discount Manager (Server)
Time-limited discount management with overlap prevention and automatic expiry.
Z Report Manager (Server)
Revenue analytics computing totals, tips, payment breakdown, and discount statistics from order logs.
Stock Market (Server)
Registers a wholesale shop in ox_inventory restricted to restaurant job grades.
Admin Manager (Server)
Admin-only restaurant creation, deletion, and location management protected by ACE permissions.
π€ Exports Reference
Instance Manager
-- Server-side exports
exports['spc-restaurant_management']:GetRestaurant(jobName) -- Get restaurant instance (lazy loads)
exports['spc-restaurant_management']:GetRestaurantId(jobName) -- Get SQL ID
exports['spc-restaurant_management']:GetPlayerRestaurant(source) -- Get player's restaurant
exports['spc-restaurant_management']:GetPlayerJobGrade(source) -- Get player's job grade
exports['spc-restaurant_management']:HasPlayerPermission(source, perm) -- Check permission
exports['spc-restaurant_management']:GetAllRestaurants() -- Get all loaded instances
exports['spc-restaurant_management']:GetRestaurantCount() -- Count loaded restaurants
exports['spc-restaurant_management']:CreateRestaurantInstance(data) -- Create new instance
exports['spc-restaurant_management']:InvalidateCache(jobName) -- Clear specific cache
exports['spc-restaurant_management']:InvalidateAllCache() -- Clear all cache
exports['spc-restaurant_management']:PreloadAllRestaurants() -- Warm-up all restaurantsMenu Manager
exports['spc-restaurant_management']:AddMenuItem(jobName, data)
exports['spc-restaurant_management']:RemoveMenuItem(jobName, menuId)
exports['spc-restaurant_management']:UpdateMenuItem(jobName, menuId, data)
exports['spc-restaurant_management']:GetRestaurantMenu(jobName)
exports['spc-restaurant_management']:GetMenuItem(jobName, menuId)Order Manager
exports['spc-restaurant_management']:CreateOrder(source, jobName, items)
exports['spc-restaurant_management']:GetOrder(jobName, orderId)
exports['spc-restaurant_management']:GetRestaurantOrders(jobName, statusFilter?)
exports['spc-restaurant_management']:GetOrderQueue(jobName)
exports['spc-restaurant_management']:UpdateOrderStatus(jobName, orderId, status)
exports['spc-restaurant_management']:CancelOrder(jobName, orderId, reason?)
exports['spc-restaurant_management']:GetOrderHistory(jobName, limit?, offset?)Recipe Manager
exports['spc-restaurant_management']:CreateRecipe(jobName, recipeData)
exports['spc-restaurant_management']:DeleteRecipe(jobName, recipeId)
exports['spc-restaurant_management']:GetRecipe(jobName, recipeId)
exports['spc-restaurant_management']:GetRestaurantRecipes(jobName)
exports['spc-restaurant_management']:GetRecipeByMenuId(jobName, menuId)
exports['spc-restaurant_management']:CanCraft(source, jobName, recipeId, isDefault, stationType)
exports['spc-restaurant_management']:ConsumeIngredients(source, recipe)
exports['spc-restaurant_management']:GetStationRecipes(jobName, stationType)
exports['spc-restaurant_management']:GetRecipeCookTime(recipe)Kitchen Manager
exports['spc-restaurant_management']:GetPendingKitchenTasks(jobName)
exports['spc-restaurant_management']:GetStationPendingTasks(jobName, stationType)
exports['spc-restaurant_management']:GetItemStationType(jobName, itemName)
exports['spc-restaurant_management']:GetOrderProgress(jobName, orderId)
exports['spc-restaurant_management']:GetKitchenOverview(jobName)Station Manager
exports['spc-restaurant_management']:GetCookingStationProcesses(stationType)
exports['spc-restaurant_management']:ProcessItem(source, stationType, processId)
exports['spc-restaurant_management']:AssembleRecipe(source, jobName, recipeId, isDefault, stationType, orderId?)
exports['spc-restaurant_management']:CanProcessItem(source, stationType, processId)
exports['spc-restaurant_management']:CanAssembleRecipe(source, recipe)Settings Manager
exports['spc-restaurant_management']:AddInteractionPoint(jobName, type, coords, stationType?)
exports['spc-restaurant_management']:RemoveInteractionPoint(jobName, pointId)
exports['spc-restaurant_management']:GetInteractionPoints(jobName)
exports['spc-restaurant_management']:GetSettings(jobName)
exports['spc-restaurant_management']:UpdateSettings(jobName, settings)
exports['spc-restaurant_management']:UpdateSetting(jobName, key, value)
exports['spc-restaurant_management']:SetRestaurantOpen(jobName, isOpen)
exports['spc-restaurant_management']:IsRestaurantOpen(jobName)Receipt Manager
exports['spc-restaurant_management']:CreateReceipt(cashierSource, metadata)
exports['spc-restaurant_management']:RedeemReceipt(source, slot, payoutMethod)
exports['spc-restaurant_management']:RedeemAllReceipts(source, payoutMethod)
exports['spc-restaurant_management']:GetReceipts(source)
exports['spc-restaurant_management']:GetTotalReceiptValue(source)Discount Manager
exports['spc-restaurant_management']:CreateDiscount(jobName, type, percentage, targets, hours, createdBy?)
exports['spc-restaurant_management']:GetActiveDiscounts(jobName)
exports['spc-restaurant_management']:GetAllDiscounts(jobName)
exports['spc-restaurant_management']:StopDiscount(jobName, discountId)
exports['spc-restaurant_management']:CheckDiscount(jobName, menuId, category)
exports['spc-restaurant_management']:ApplyDiscount(jobName, menuId, originalPrice, category)
exports['spc-restaurant_management']:CleanupExpiredDiscounts()Z Report Manager
exports['spc-restaurant_management']:GetOpenPeriodReport(jobName)
exports['spc-restaurant_management']:GetDailyReport(jobName)
exports['spc-restaurant_management']:GetDateRangeReport(jobName, startDate, endDate)
exports['spc-restaurant_management']:CalculateReport(restaurantId, startTime, endTime)π Bridge System
The bridge auto-detects your framework at runtime and provides a unified API:
shared/bridge/
βββ init.lua β Detects qbx_core / qb-core / es_extended, ox_inventory / qb-inventory, ox_target / qb-target
βββ core/
β βββ qb.lua β QBX & QB-Core server+client adapter
β βββ esx.lua β ESX server+client adapter
βββ inventory/
β βββ ox.lua β ox_inventory adapter
β βββ qb.lua β qb-inventory / ps-inventory adapter
βββ target/
βββ ox.lua β ox_target adapter
βββ qb.lua β qb-target adapterBridge API
| Function | Side | Purpose |
|---|---|---|
Bridge.GetPlayer(source) | Server | Get normalized player object with PlayerData, Functions.AddMoney/RemoveMoney/GetMoney |
Bridge.GetPlayerData() | Client | Get local player data (citizenid, charinfo, job) |
Bridge.DoesJobExist(jobName) | Server | Check if a job exists in the framework |
Bridge.OpenBossMenu(jobName) | Client | Open the management/boss menu |
Bridge.Inventory.AddItem(...) | Server | Add item to player inventory |
Bridge.Inventory.RemoveItem(...) | Server | Remove item from player inventory |
Bridge.Inventory.GetItemCount(...) | Both | Get item count |
Bridge.Inventory.RegisterStash(...) | Server | Register a stash (tray/storage/kitchen pass) |
Bridge.Inventory.OpenStash(stashId) | Client | Open a stash UI |
Bridge.Target.AddBoxZone(data) | Client | Add a target box zone |
Bridge.Target.AddLocalEntity(entity, options) | Client | Add target to entity |
Bridge.Target.RemoveZone(zoneId) | Client | Remove target zone |
π Localization
The system uses ox_lib locale with JSON translation files:
locales/
βββ en.json β English (default)
βββ tr.json β TurkishSet the locale in your ox_lib configuration or server.cfg:
setr ox:locale enAll UI strings, notifications, and menu labels reference locale keys via locale('key_name', ...).
π Permission System
Permissions are grade-based. The Config.Permissions table maps actions to minimum required job grade levels.
| Grade | Example Role | Accessible Features |
|---|---|---|
| 0 | Employee | Cashier, Order Point |
| 1 | Chef | Kitchen, Storage, all above |
| 2+ | Manager | Menu editing, Settings, Discounts, Z Report, Receipts, Interaction points, all above |
Admin operations (creating/deleting restaurants) require the command.restaurantadmin ACE permission.
β FAQ & Troubleshooting
Q: Restaurants don't appear after server restart?
A: Restaurants are lazy-loaded. They load on first player interaction. Use PreloadAllRestaurants() export if you want warm-up at startup.
Q: Orders disappear after restart?
A: By design. Active orders live only in RAM. Completed/cancelled orders are logged to lcky_orders_log.
Q: Restaurant is always closed after restart?
A: Intentional. ResetAllRestaurantsOpenStatus() runs on resource start. A manager must open the restaurant each session.
Q: How do I add a new restaurant?
A: 1) Add the job to your framework. 2) Add it to Config.Restaurants and Config.RestaurantJobs. 3) Use /restaurantadmin in-game to register it with coordinates.
Q: How do I add new cooking station processes?
A: Edit shared/config_stations.lua β Add entries to Config.CookingStations[stationType].processes.
Q: How do I add new assembly ingredients?
A: Add entries to Config.AssemblyIngredients in config_stations.lua.
Q: How do I add a new menu category?
A: Add an entry to Config.MenuCategories in config.lua.
π License
This resource is developed by LuckyScripts. All rights reserved.
Version: 1.0.0 | Author: LuckyScripts | Game: GTA V (FiveM)