> For the complete documentation index, see [llms.txt](https://documentation.rcore.cz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://documentation.rcore.cz/paid-resources/rcore_dealership/api/server.md).

# Server

Use these exports to read or manage dealership data from another resource. Call them on the server.

{% hint style="warning" %}
The dealership management exports are admin-gated - they check `Framework.isAdmin(playerId)` for the player you pass in.
{% endhint %}

## 🏢 Dealership Management

<details>

<summary>addDealership</summary>

Creates a new dealership.

```lua
---@param playerId number | Admin who is creating the dealership
---@param dealership table | Dealership payload (name, type, area, points, business?, framework_job?, blip?)
---@return table result | { success: boolean, error?: string, dealershipId?: string }
local result = exports.rcore_dealership:addDealership(playerId, dealership)
```

Admin only. Validates the payload (name, type, area polygon, and required points) and broadcasts the new dealership to all clients.

</details>

<details>

<summary>updateDealership</summary>

Updates an existing dealership.

```lua
---@param playerId number | Admin performing the update
---@param dealership table | Dealership payload including numeric `id`
---@return table result | { success: boolean, error?: string }
local result = exports.rcore_dealership:updateDealership(playerId, dealership)
```

Admin only. Changing `framework_job` clears the dealership's existing permissions.

</details>

<details>

<summary>deleteDealership</summary>

Deletes a dealership.

```lua
---@param playerId number | Admin performing the deletion
---@param dealershipId number
exports.rcore_dealership:deleteDealership(playerId, dealershipId)
```

Admin only. Broadcasts the deletion to all clients.

</details>

<details>

<summary>updateDealershipPoint</summary>

Updates a single named point of a dealership.

```lua
---@param playerId number | Admin performing the update
---@param dealershipId number
---@param pointName string | Zone/point key
---@param coords table | New point coordinates
exports.rcore_dealership:updateDealershipPoint(playerId, dealershipId, pointName, coords)
```

Admin only.

</details>

<details>

<summary>deleteDealershipPoint</summary>

Removes a named point from a dealership.

```lua
---@param playerId number | Admin performing the change
---@param dealershipId number
---@param pointName string | Point key to remove
exports.rcore_dealership:deleteDealershipPoint(playerId, dealershipId, pointName)
```

Admin only.

</details>

<details>

<summary>addDealershipModels</summary>

Adds vehicle models to a dealership's catalog.

```lua
---@param playerId number | Admin performing the change
---@param dealershipId number
---@param models table|nil | Map of model -> { price = number|nil }. If nil, auto-adds all models matching the dealership type.
---@return table result | { success: boolean, error?: string, addedModels?: string[] }
local result = exports.rcore_dealership:addDealershipModels(playerId, dealershipId, models)
```

Admin only. Models already in the catalog are skipped.

</details>

<details>

<summary>deleteDealershipModels</summary>

Removes vehicle models from a dealership's catalog.

```lua
---@param playerId number | Admin performing the change
---@param dealershipId number
---@param models table|nil | Array of model name strings to remove. If nil, removes ALL models.
---@return table result | { success: boolean, error?: string }
local result = exports.rcore_dealership:deleteDealershipModels(playerId, dealershipId, models)
```

Admin only. Note `models` here is a list of model names, not a map. Passing `nil` clears every model.

</details>

## 👔 Employees & Permissions

<details>

<summary>getDealershipTopEmployee</summary>

Returns the top employee of the current period for a dealership.

```lua
---@param dealershipId number
---@return table|nil employee | { actor_identifier, actor_name, total_revenue, total_stocked, total_orders, total_test_drives }
local employee = exports.rcore_dealership:getDealershipTopEmployee(dealershipId)
```

Returns `nil` if there was no activity in the period. Ranked by revenue, then stock, then orders.

</details>

<details>

<summary>hasEmployeePermission</summary>

Checks whether a player's job and grade grant a permission at a business dealership.

```lua
---@param playerId number
---@param dealershipId number
---@param permission string | A DealershipPermission value
---@return boolean
local allowed = exports.rcore_dealership:hasEmployeePermission(playerId, dealershipId, permission)
```

Returns `false` if the dealership is not a business or the player's job does not match its `framework_job`.

</details>

<details>

<summary>getEmployeePermissions</summary>

Returns the full grade-to-permission map for a business dealership.

```lua
---@param playerId number | Must be employed at the dealership's job
---@param dealershipId number
---@return table permissions | { [grade] = { [permission] = true } }
local permissions = exports.rcore_dealership:getEmployeePermissions(playerId, dealershipId)
```

Returns `{}` unless the querying player works at the dealership.

</details>

<details>

<summary>setEmployeePermission</summary>

Grants or revokes a permission for a job grade at a business dealership.

```lua
---@param playerId number|nil | Actor. Must have MANAGE_PERMISSIONS. Pass nil for a trusted server-side call (skips the check).
---@param dealershipId number
---@param grade number | Job grade
---@param permission string | A DealershipPermission value
---@param enabled boolean | true to grant, false to revoke
exports.rcore_dealership:setEmployeePermission(playerId, dealershipId, grade, permission, enabled)
```

The change is audit-logged when a player performed it.

</details>

<details>

<summary>getDealershipBossJobGradeId</summary>

Returns the boss (highest) job grade id for a business dealership.

```lua
---@param dealershipId number
---@return number|nil
local bossGrade = exports.rcore_dealership:getDealershipBossJobGradeId(dealershipId)
```

</details>

## 💰 Finance

<details>

<summary>isPlateFinanced</summary>

Checks whether a plate is under an active finance contract for an identifier.

```lua
---@param identifier string | Player/character identifier (not a server id)
---@param plate string
---@return boolean
local financed = exports.rcore_dealership:isPlateFinanced(identifier, plate)
```

</details>

<details>

<summary>getPlayerFinances</summary>

Returns a player's active vehicle finance contracts with display info.

```lua
---@param playerId number
---@return table finances | Array of finance entries (balance, installments, plate, vehicle info, ...)
local finances = exports.rcore_dealership:getPlayerFinances(playerId)
```

Returns `{}` if the player's identifier cannot be resolved.

</details>

## 🔢 Purchase

<details>

<summary>validatePlate</summary>

Validates a custom plate against length, allowed characters, and uniqueness.

```lua
---@param plate string
---@return boolean valid
---@return string|nil reason | A PurchaseReason (PLATE_INVALID, PLATE_TOO_SHORT, PLATE_TOO_LONG, PLATE_TAKEN)
---@return any extra | Min/max length for the length errors
local valid, reason = exports.rcore_dealership:validatePlate(plate)
```

Length bounds come from `Config.Dealership.Purchase.CustomPlate`.

</details>

## 📋 NPC Orders

<details>

<summary>generateNpcOrder</summary>

Generates a random NPC vehicle order for a business dealership.

```lua
---@param dealershipId number
---@return number|nil orderId
local orderId = exports.rcore_dealership:generateNpcOrder(dealershipId)
```

Returns `nil` if the dealership is not a business, has no models, or has no models under the value cap. The Billboard Ads upgrade raises the cap and biases orders toward pricier vehicles.

</details>

<details>

<summary>hasDealershipPendingOrders</summary>

Checks whether a dealership has any pending or in-progress orders.

```lua
---@param dealershipId number
---@return boolean
local hasOrders = exports.rcore_dealership:hasDealershipPendingOrders(dealershipId)
```

</details>

<details>

<summary>hasDealershipOnlineEmployees</summary>

Checks whether any employee of the dealership's job is online.

```lua
---@param dealershipId number
---@return boolean
local hasEmployees = exports.rcore_dealership:hasDealershipOnlineEmployees(dealershipId)
```

</details>

## 🚗 Test Drive

<details>

<summary>canPlayerStartTestDrive</summary>

Checks whether a player may start a test drive.

```lua
---@param playerId number
---@param dealershipId number
---@param driveType string | A TestDriveType value (customer or business)
---@return boolean allowed
---@return string|nil reason | A deny reason (COOLDOWN, PENALTY, WRONG_JOB, ...)
---@return any extra | Remaining time in ms for COOLDOWN/PENALTY
local allowed, reason = exports.rcore_dealership:canPlayerStartTestDrive(playerId, dealershipId, driveType)
```

Business drives require the dealership's job and the `TEST_DRIVE` permission. Customer drives check penalty and cooldown windows.

</details>

<details>

<summary>getPlayerTestDrivePenalties</summary>

Checks whether an identifier is currently banned from test drives.

```lua
---@param identifier string | Player/character identifier (not a server id)
---@return boolean allowed
---@return number|nil remainingMs | Time left on the ban when not allowed
local allowed, remainingMs = exports.rcore_dealership:getPlayerTestDrivePenalties(identifier)
```

Thresholds come from `Config.Dealership.TestDrive.Penalty`.

</details>

## ⬆️ Upgrades

<details>

<summary>hasDealershipUpgrade</summary>

Checks whether a dealership has a boolean upgrade active.

```lua
---@param dealershipId number
---@param upgrade string | A DealershipUpgrade value
---@return boolean
local hasUpgrade = exports.rcore_dealership:hasDealershipUpgrade(dealershipId, upgrade)
```

Only returns `true` for boolean upgrades. Leveled upgrades (stored as a number) are not reported here - use `getDealershipUpgrades` to read their level.

</details>

<details>

<summary>getDealershipUpgrades</summary>

Returns all upgrades for a dealership.

```lua
---@param dealershipId number
---@return table upgrades | { [upgrade] = true | level(number) }
local upgrades = exports.rcore_dealership:getDealershipUpgrades(dealershipId)
```

Returns `{}` for non-business or unloaded dealerships.

</details>

## 🧾 Audit

<details>

<summary>recordAudit</summary>

Writes an audit-log entry for a business dealership and notifies open tablets.

```lua
---@param dealershipId number
---@param action string | An AuditAction key
---@param playerId number | Player who performed the action
---@param value any | Optional logged value (tables are JSON-encoded)
---@param metadata table | Optional extra data (JSON-encoded)
exports.rcore_dealership:recordAudit(dealershipId, action, playerId, value, metadata)
```

Silently ignored if the dealership is not a loaded business or the player's identifier cannot be resolved.

</details>
