# Frameworks

Framework Compatibility — moh-billing

moh-billing supports both **QBCore** and **ESX** through a\
shared abstraction layer called `bridge.lua`. Switching between frameworks\
requires changing **one line** in `config.lua`.

### Switching frameworks

Open `config.lua` and change:

```
Config.Framework = 'qbcore'   -- change to 'esx' for ESX servers
```

That is the only change needed for most setups. If your ESX or QBCore resource has\
a non-standard export/event name, also update:

```
-- QBCore (if your resource is named differently, e.g. 'qb-core-custom')
Config.QBCoreExport = 'qb-core'
-- ESX legacy (default)
Config.ESXEvent = 'esx:getSharedObject'
```

### What the bridge provides

`bridge.lua` is a *shared script* (runs on both client and server).\
It exposes a unified `Bridge` table so the rest of the resource never calls\
framework-specific functions directly.

| Function                                | Side   | Description                                                                           |
| --------------------------------------- | ------ | ------------------------------------------------------------------------------------- |
| `Bridge.GetPlayer(source)`              | Server | Returns a normalised player object (see below).                                       |
| `Bridge.GetPlayerByCitizenId(id)`       | Server | Looks up a player by their citizen/identifier and returns the same normalised object. |
| `Bridge.RemoveMoney(player, amount)`    | Server | Deducts money from the account defined in `Config.MoneyAccount`.                      |
| `Bridge.AddMoney(player, amount)`       | Server | Adds money to the account defined in `Config.MoneyAccount`.                           |
| `Bridge.Notify(source, msg, type, ms)`  | Server | Sends an in-game notification to a player.                                            |
| `Bridge.IsBoss(job, grade)`             | Shared | Returns `true` if the given grade meets the minimum boss grade for the job.           |
| `Bridge.GetPlayerData()`                | Client | Returns the local player's data.                                                      |
| `Bridge.GetClosestPlayer()`             | Client | Returns the closest player handle and distance.                                       |
| `Bridge.ClientNotify(msg, type, ms)`    | Client | Shows a local notification.                                                           |
| `Bridge.TriggerCallback(name, cb, ...)` | Client | Triggers a server callback in the framework's native style.                           |

### Normalised player object

`Bridge.GetPlayer()` always returns the same fields regardless of framework:

```
{
    source    = number,   -- player server ID
    citizenid = string,   -- QBCore citizenid / ESX identifier
    name      = string,   -- "Firstname Lastname"
    money     = number,   -- current balance of Config.MoneyAccount
    job       = string,   -- job name
    jobLabel  = string,   -- job display label
    grade     = number,   -- job grade level (integer)
    isBoss    = boolean,  -- grade >= Config.BossGrades[job] or Config.DefaultBossGrade
    _raw      = table,    -- original framework player object (advanced use)
}
```

### Grade mapping

| Framework | Source field                 | Notes                                                                 |
| --------- | ---------------------------- | --------------------------------------------------------------------- |
| QBCore    | `PlayerData.job.grade.level` | Integer starting at 0. Default QBCore jobs typically have 3–4 grades. |
| ESX       | `job.grade`                  | Integer. Defined in the `job_grades` table of your ESX database.      |

### Adding a third framework

All framework-specific code is isolated in `bridge.lua`. To add support\
for another framework (e.g. OX Core), add a new `elseif` block that\
populates the same `Bridge.*` functions described above.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mohssins.gitbook.io/mohscriptsdocs/moh-billing/frameworks.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
