Introduction
🚗 aty_dealershipv2
A fully-featured, player-owned vehicle dealership system for FiveM (ESX / QBCore)
Version2.0.1· Authoratiysu· Framework-agnostic viaaty_lib
📖 Overview
aty_dealershipv2 is an advanced, fully database-driven vehicle dealership resource for FiveM servers. It supports unlimited, fully customisable dealerships that can be either:
- Self-Served – Managed by server admins only; players can browse and buy freely.
- Player-Owned – Players can purchase, own, and manage entire dealerships as a business. Owners stock vehicles, set prices, run discounts, issue coupons, deliver ordered stock, and collect revenue to their dealership's balance.
The UI is built with Vue 3 + Vite and communicates over NUI callbacks. All dealership data is persisted in a MariaDB/MySQL database.
✨ Features
| Category | Feature |
|---|---|
| Dealerships | Unlimited dealerships, each with its own location set |
| Shop Types | self-served (admin-only management) and owned (player-managed) |
| Purchasing | Cash, Bank Card, or Installment (Finance) payments |
| Finance | Configurable interest rate, late fees, maximum months, first-payment requirement |
| Installments | Player installment dashboard, pay monthly or in full, overdue tracking |
| Coupons | Owner/admin creates coupon codes with % discount, expiry time, and usage limit |
| Discounts | Time-limited, usage-capped per-vehicle discounts |
| Ordering | Realistic order delivery mission – spawn truck, hitch trailer, deliver to dealership |
| Showcase | Owners place real vehicles at custom world positions as showroom displays |
| Test Drive | Isolated routing bucket per test drive, timer countdown |
| Admin Panel | Full in-game CRUD for dealerships and the global vehicle catalog |
| Targets | Optional target interaction (works with aty_lib target module) |
| Exports | Rich Lua exports for integration with other resources |
| Dual-Framework | Supports both ESX and QBCore via aty_lib |
| Customisable UI | All colours fully configurable from config.lua without touching source code |
| Job Restriction | Restrict any dealership to a specific job or leave it open to all |
📦 Dependencies
| Dependency | Notes |
|---|---|
aty_lib |
Required – provides framework abstraction, callbacks, SQL helpers, and shared utilities |
oxmysql or compatible |
Required by aty_lib for database queries |
| ESX or QBCore | One framework must be present and started before aty_lib |
Note:
aty_libmust be started beforeaty_dealershipv2in yourserver.cfg.
🛠️ Installation
Database Setup
Fresh install – run data.sql:
-- Creates the main dealership table and the vehicle_installments table
SOURCE aty_dealershipv2/data.sql
Updating from an older version – run update.sql instead:
-- Creates vehicle_installments if missing and adds the `coupons` column
SOURCE aty_dealershipv2/update.sql
The two tables created are:
| Table | Purpose |
|---|---|
aty_dealership |
Stores every dealership: locations, vehicles, orders, sales, listings, coupons, balance |
vehicle_installments |
Tracks active finance/installment debt per player |
Resource Setup
- Copy the
aty_dealershipv2folder into your resources directory (e.g.resources/[aty]/). - Add the following lines to your
server.cfgafteraty_lib:
ensure aty_lib
ensure aty_dealershipv2
- Import the SQL file(s) described above into your database.
- Restart your server or use
refresh+start aty_dealershipv2.
⚙️ Configuration Reference
All configuration lives in shared/config.lua. Changes here apply to both client and server automatically.
General Settings
Config = {
Target = false, -- true = use ox_target/qtarget zones, false = proximity markers
RealisticOrder = true, -- true = order delivery requires driving the truck
OrderCooldown = 1, -- minutes between orders (per dealership)
DefaultStock = 1, -- fallback stock when not specified
MaxListings = 5, -- max showcase vehicle listings per dealership
TestTime = 60, -- test-drive time limit in seconds
| Key | Type | Description |
|---|---|---|
Target |
boolean |
Enable ox_target-style zone interactions instead of proximity DrawText3D |
RealisticOrder |
boolean |
Requires the owner to drive a delivery truck to restock vehicles |
OrderCooldown |
number |
Minutes before another order can be placed on the same shop |
DefaultStock |
number |
Stock assigned to a vehicle if none is specified |
MaxListings |
number |
Maximum number of showcase listings per dealership |
TestTime |
number |
Seconds a player gets for a test drive |
Order Pickup Locations – the array of vector4 coordinates where delivery trucks spawn:
OrderPickupLocation = {
vector4(1204.3624, -3099.4116, 5.8572, 0.0),
-- add more pickup points as needed
},
OrderTruckModel = "phantom", -- GTA model name for the delivery truck
OrderTrailerModel = "tr4", -- GTA model name for the trailer
Finance Settings
PaymentInterval = 24, -- hours between installment payments (24 = daily)
MaxInstallmentMonths = 24, -- maximum months a player can spread payments over
MaxActiveInstallments = 3, -- max concurrent installment contracts per player
FinanceInterest = 0.05, -- 5% interest added to the total financed price
FinanceLateFee = 0.02, -- 2% compounding fee per overdue interval
FinanceCheckFullPrice = true, -- player must have full vehicle price in bank to finance
FinanceFirstPaymentRequired = true, -- first monthly payment is deducted immediately on purchase
| Key | Description |
|---|---|
PaymentInterval |
Use 12 = every 12 h, 24 = daily, 168 = weekly, 720 = monthly |
FinanceInterest |
Multiplied onto selling price → total financed amount |
FinanceLateFee |
Applied per each missed interval, compounding on the remaining balance |
FinanceCheckFullPrice |
Safety check – prevents players from taking finance they cannot theoretically repay |
FinanceFirstPaymentRequired |
Deducts the first monthly instalment at the moment of purchase |
UI Theme
Every colour used in the NUI can be overridden without touching Vue source code:
UI = {
PrimaryColor = "#69ffec", -- Main accent / highlight colour
PrimaryColorDark = "#3f998e", -- Darker shade of accent
BackgroundPrimary = "#0c0e12", -- Main panel background
BackgroundSecondary = "#2c2f3a", -- Card / secondary panel colour
TextPrimary = "#ffffff",
TextSecondary = "#999999",
ButtonPrimaryStart = "#69ffec", -- Gradient start for primary buttons
ButtonPrimaryEnd = "#3f998e", -- Gradient end for primary buttons
StatusSuccess = "#1f8a43",
StatusWarning = "#d78024",
StatusError = "#eb3333",
StatusDanger = "#d03737",
},
Interaction Zones
Controls the radius and visibility distance for each interaction point:
Interactions = {
ZoneRadius = 4.0, -- radius of the main shop / ped zone
ZoneDistance = 4.0, -- draw distance for the zone prompt
ManageRadius = 2.0, -- boss management dashboard zone
ManageDistance = 2.0,
PurchaseRadius = 2.0, -- "purchase this dealership" zone
PurchaseDistance = 2.0,
ShowcaseRadius = 2.0, -- around showcase-listed vehicles
ShowcaseDistance = 2.0,
},
Vehicle Stats
Controls how vehicle performance data is fetched and displayed:
VehicleStats = {
AWD_Threshold = 0.3, -- acceleration value above which drivetrain reads "AWD"
Normalization = {
Speed = { 100, 180 }, -- km/h min/max for bar chart
Acceleration = { 0.1, 0.4 },
Handling = { 20, 45 },
Braking = { 0.0, 1.0 },
Traction = { 1, 3 },
}
},
Callbacks & Hooks
OnVehiclePurchase
Called server-side every time a vehicle is successfully purchased:
OnVehiclePurchase = function(source, model, plate, price, method)
-- source = player server ID
-- model = vehicle model string
-- plate = generated license plate
-- price = final price after discounts/coupons
-- method = "cash" | "bank" | "finance"
-- Example: award XP, log to Discord, grant keys, etc.
print(string.format("Player %s bought %s (%s) for $%s via %s", source, model, plate, price, method))
end
🏪 Dealership Types
| Type | Description |
|---|---|
self-served |
No owner. All vehicles are permanently in stock. Admins manage everything through the admin panel. Ideal for government/public dealerships. |
owned |
Can be purchased by a player. The owner manages stock, orders, listings, prices, discounts, coupons, and the dealership's balance. |
🛡️ Admin Panel Guide
Opening the Admin Panel
Use the in-game command (default: dealershipadmin):
/dealershipadmin
This command is restricted to the permission levels defined in:
Config.AdminPermissions = { "god", "admin", "superadmin" }
For QBCore, these are QBCore permission levels. For ESX, these map to ESX account ranks.
Creating a Dealership
- Run
/dealershipadminto open the admin panel. - Click the Create (➕) button in the top-right.
- Fill in the creation form:
| Field | Description |
|---|---|
| Name | Unique identifier for the dealership (no spaces recommended) |
| Price | Cost for a player to purchase this dealership (set 0 if not for sale) |
| Blip ID | GTA map blip sprite ID (see blip sprites reference) |
| Job | all for everyone, or a job name (e.g. mechanic) to restrict access |
| Ped Model | Model name for the salesperson NPC (default: ig_siemonyetarian) |
| Type | owned or self-served |
| Locations | Click each button and confirm placement in the world |
| Categories | Select which vehicle categories appear in this dealership's stock |
- Locations – You must set all 8 points:
| Location | Purpose |
|---|---|
Dashboard |
Where the boss management menu is accessed (marker) |
Dealership |
Position of the map blip |
Purchase |
Zone where players can buy the dealership itself |
Ped |
Where the salesperson NPC spawns |
Preview |
Where vehicles are shown in the shopping camera |
Spawn |
Where the purchased vehicle appears after buying |
Test |
Where the vehicle spawns for a test drive |
Order Point |
Where the delivery truck arrives after an order |
- Click Create to save. The dealership appears on all connected clients immediately.
Editing a Dealership
- Open the admin panel.
- Find the dealership in the list and click the Edit (⚙️) icon.
- Modify any fields and re-set any locations as needed.
- Click Update.
All connected clients receive the updated dealership data in real time.
Deleting a Dealership
- Open the admin panel.
- Click the Delete icon next to the dealership.
- Confirm in the popup.
This permanently removes the dealership and all its data from the database.
Managing the Vehicle Catalog
The global vehicle catalog (shared/catalog.lua) defines every vehicle available to any dealership. Admins can manage it in-game:
- Open
/dealershipadmin. - Click Edit Vehicles (pencil icon).
- Select the vehicle you want to modify from the dropdown.
- Edit its Name, Label, Model, Price, and Category.
- Alternatively click Delete to remove it from the catalog entirely.
To add a new vehicle to the catalog, use the addVehicleToCatalog server callback or manually add it to shared/catalog.lua.
Changes to the catalog are saved directly to
shared/catalog.luaand broadcast to all clients.
👤 Player Guide
Browsing Vehicles
- Approach the dealership NPC on the map (look for the blip icon).
- Press [E] when the prompt appears to open the shop menu.
- Use the search bar to filter by vehicle name.
- Use the category tabs at the top to filter by type (Cars, Bikes, Boats, etc.).
- Click any vehicle to select it – a live 3D preview will spawn at the preview point.
- Scroll to rotate the 3D preview model.
- Pinch / scroll wheel to zoom.
- View the vehicle's Technical Specifications panel:
- Max Speed, Acceleration, Braking, Traction, Seats, Drivetrain
Test Drive
- Select a vehicle in the shop menu.
- Click Test Drive.
- The vehicle spawns at the test drive location. You have
Config.TestTimeseconds (default 60 s) before it is automatically returned. - Exit the vehicle at any time to end the test drive early.
Test drives are isolated in a routing bucket – other players cannot see or interact with the test drive vehicle.
Purchasing a Vehicle
- Select a vehicle in the shop menu.
- Choose your primary colour and secondary colour using the colour pickers.
- (Optional) Enter a coupon code and click Apply to receive a discount.
- Choose your payment method:
| Method | Requirements |
|---|---|
| Pay with Card (Bank) | Must have sufficient bank balance |
| Pay with Cash | Must have sufficient cash on hand |
| Pay with Installments (Finance) | See finance conditions below |
- If using Finance:
- Select the number of months (1 –
MaxInstallmentMonths). - The UI shows the monthly payment and total amount with interest.
- If
FinanceCheckFullPrice = true, you need the full vehicle price in your bank. - If
FinanceFirstPaymentRequired = true, the first instalment is deducted immediately.
- Select the number of months (1 –
- Confirm the purchase. The vehicle spawns at the dealership spawn point with:
- Your chosen colours applied.
- Your vehicle keys granted (via
aty_libkey export). - A full fuel tank (100%).
- A unique license plate.
Using Coupons
- In the purchase panel, locate the Coupon Code input.
- Type the code provided by the dealership owner and click Apply.
- If valid, the discount percentage is shown and the total price is reduced.
- Coupons can expire or have a usage limit – if either is exceeded, the code is rejected.
Installment Payments
- Use the command
/installments(default) to open your Installments Dashboard. - All active finance contracts are listed, showing:
- Vehicle name and plate
- Total debt / remaining balance
- Monthly payment amount
- Next payment due date
- Overdue status
- Click Make Payment to pay one monthly instalment.
- Click Pay in Full to clear the entire remaining balance in one go.
Late Fees: If a payment is missed, a
FinanceLateFeepercentage is compounded onto the remaining balance for each overdue interval.
💼 Dealership Owner (Boss) Guide
Accessing the Boss Menu
- Go to your dealership's Dashboard marker (the location you set when creating it).
- Press [E] when the prompt appears.
- The Boss Menu opens, with tabs for: Dashboard, Stock, Orders, Sales, Vehicle Listing, Coupons.
Dashboard
Displays a real-time overview:
- Account Balance – money in the dealership's safe.
- Vehicles in Stock – total units across all models.
- Listed Vehicles – number of active showcase listings.
- Total Sales – revenue broken down by Day / Week / Month / Year.
Stock Management & Ordering
Navigate to the Stock tab:
- All vehicles in your dealership's catalog are listed with their current stock levels.
- For each vehicle you can:
- Edit Price – set your own selling price (independent of the catalog base price).
- Order Vehicle – place a restock order (see below).
- Set Discount – configure a time-limited sale.
- Remove Discount – cancel an active discount.
Order Delivery Mission
When RealisticOrder = true (default):
- In the Stock tab, click Order Vehicle for the model you want.
- Enter the quantity and confirm. The order cost is deducted from your bank immediately.
- You receive a notification when the delivery truck has arrived.
- Travel to the truck blip on your map. Get into the Phantom truck.
- A new blip directs you to the docks to pick up the trailer – drive there and attach the trailer.
- A final blip shows your dealership's order point. Drive the truck+trailer there.
- Press [E] at the delivery marker to complete the delivery.
- The ordered vehicles are added to your stock automatically.
Only one active order can be in progress at a time per dealership.
Vehicle Listings (Showcase)
The Vehicle Listing tab lets you place physical showcase vehicles in the world:
- Click Create Listing.
- Select the vehicle from your catalog.
- Choose a colour.
- The location selector opens in-world – aim at the ground where you want the car placed and confirm.
- The vehicle spawns, frozen in place. Players who walk up to it see stats and price information.
Maximum listings per dealership: Config.MaxListings (default 5).
To remove a listing:
- Open the Vehicle Listing tab.
- Click Delete Listing next to the entry and confirm.
Discounts
- Go to the Stock tab.
- Click Set Discount on a vehicle.
- Configure:
- Percentage % – how much off (e.g.
20= 20% discount) - Duration (hours) – how long the discount is active
- Usage Limit – maximum times the discount can be applied before it expires
- Percentage % – how much off (e.g.
- Click Apply. The discounted price is calculated automatically at checkout.
- Click Remove Discount to end it early.
Coupons
- Go to the Coupons tab.
- Click Create Coupon.
- Fill in:
- Code – unique alphanumeric code players will type at checkout
- Percentage % – discount value
- Duration (hours) – expiry window
- Usage Limit – max redemptions
- Share the code with your customers. When a player redeems it, the usage count decrements.
- Delete expired or unwanted coupons at any time.
Sales History
The Sales tab shows a chronological log of every vehicle sold:
| Column | Description |
|---|---|
| Vehicle | Model name |
| Price | Amount charged |
| Payment Type | cash / bank / finance |
| Date | Timestamp of the sale |
Treasury (Deposit / Withdraw)
The Dashboard tab contains the dealership's Account Balance with two actions:
- Deposit – move money from your bank into the dealership safe.
- Withdraw – move money from the dealership safe to your bank.
Revenue from vehicle sales is automatically added to the dealership balance.
When customers pay installments, each payment also flows to the dealership balance.
📡 Exports API
These Lua exports are available to other resources:
-- Open the main shop UI for the closest dealership
exports["aty_dealershipv2"]:openDealership()
-- Open the player's installments dashboard
exports["aty_dealershipv2"]:openInstallments()
-- Returns a table of all shops (same structure as DB rows, decoded)
local shops = exports["aty_dealershipv2"]:getShops()
-- Returns data for a single shop by name
local shop = exports["aty_dealershipv2"]:getShopData("LuxuryCars")
-- Returns all active installments for the local player
local installments = exports["aty_dealershipv2"]:getPlayerInstallments()
-- Returns a single installment by its database ID
local inst = exports["aty_dealershipv2"]:getInstallmentById(5)
-- Returns the vehicle list (with stock > 0) for a shop
local vehicles = exports["aty_dealershipv2"]:getDealershipVehicles("LuxuryCars")
💻 Commands Reference
| Command | Permission | Description |
|---|---|---|
/dealershipadmin |
Admin (god / admin / superadmin) |
Opens the admin management panel |
/directsale |
— | (Reserved / configurable) |
/installments |
Any player | Opens the installment payment dashboard |
Command names can be changed in config.lua:
Commands = {
Admin = "dealershipadmin",
DirectSale = "directsale",
Installments = "installments",
},
📚 Catalog (shared/catalog.lua)
The catalog is a Lua table where each key is the vehicle's internal identifier:
Catalog = {
["adder"] = {
name = "Adder", -- short display name
label = "Truffade", -- manufacturer / brand
model = "adder", -- GTA spawn model name
price = 1000000, -- base purchase price in $
category = "Super", -- category string (used to filter per dealership)
},
-- ...
}
The catalog file is written/saved by the admin panel. You can also edit it manually – just restart the resource afterwards.
🌐 Locale / Translations
Language strings are in shared/locale.lua. The active locale is set at the top:
Locale = 'en'
To add a new language, duplicate the ["en"] block and change the key:
Locales = {
["en"] = { ... },
["tr"] = {
['no_vehicles_for_sale'] = "Bu galeride satılık araç yok",
-- ... all keys
}
}
Then set Locale = 'tr' at the top of the file.
📁 File Structure
aty_dealershipv2/
├── client/
│ └── client.lua # All client-side logic (UI control, camera, preview, zones)
├── server/
│ ├── server.lua # All server callbacks (purchasing, orders, installments, etc.)
│ └── admin.lua # Admin commands, dealership CRUD, catalog management
├── shared/
│ ├── config.lua # ⬅ Main configuration file
│ ├── catalog.lua # Global vehicle catalog (read/written by admin panel)
│ └── locale.lua # Localisation strings
├── web/ # Vue 3 + Vite NUI source
│ └── src/
│ ├── components/ # ShopMenu, BossMenu, AdminMenu, Installments, Showcase…
│ ├── stores/ # Pinia state management
│ └── utils/ # fetchNui helper
├── ui/ # Compiled NUI output (served by FiveM)
├── data.sql # Fresh install database schema
├── update.sql # Incremental migration for existing installs
└── fxmanifest.lua # Resource manifest
🔧 Troubleshooting
Dealership NPC / Blip not appearing
- Ensure the resource started without errors (
server console). - Check that the database import was successful and at least one row exists in
aty_dealership. - Verify
aty_libis started beforeaty_dealershipv2.
UI opens but vehicles don't load
- The
shared/catalog.luamay be empty or malformed. Check the file for syntax errors. - Confirm the dealership has vehicles assigned (categories were selected when creating it).
"aty_lib" not found error
- Ensure
aty_libis downloaded and listed inserver.cfgbefore this resource.
Finance / installments not working
- Confirm the
vehicle_installmentstable exists. Runupdate.sqlif upgrading. - Check
Config.PaymentIntervalis set correctly.
Order delivery mission doesn't trigger
- Ensure
Config.RealisticOrder = true. - Check that
OrderTruckModelandOrderTrailerModelare valid GTA V model names on your server. - Verify the
OrderPickupLocationcoordinates are reachable and not inside an interior.
Admin command not working
- Confirm the player's ESX grade / QBCore permission matches one of the
Config.AdminPermissionsvalues. - Check the console for any errors when starting the resource.
📄 License
This resource is the intellectual property of atiysu. Redistribution, resale, or public release without explicit permission is prohibited. For support or licensing inquiries, contact the author directly.
Made with ❤️ by atiysu