> For the complete documentation index, see [llms.txt](https://docs.gkshop.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.gkshop.org/gksphone-v2/custom-framework/server.md).

# Server

Ensure you review the `qb.lua` and `esx.lua` files to understand how the phone integrates with each framework. These files are kept up to date with the latest changes.

## Step 1: Framework Compatibility Check

At the beginning of your integration file, add a check for `Config.Framework` to avoid loading for unsupported frameworks.

```lua
if Config.Framework ~= "your-framework" then
    return
end
```

## Step 2: Required Framework Functions

Below are the essential functions you need to implement for the phone to function correctly with your custom framework.

### GetIdentifier

Retrieve the current character's identifier. For multi-character setups, return the active character's identifier.

```lua
function GetIdentifier(source)
    -- This is an example from the gksphone esx.lua file
    return Config.Core.GetPlayerFromId(source)?.identifier
end
```

### GetPlayerFromIdentifier

Check if a character is online using their identifier.

```lua
function GetPlayerFromIdentifier(identifier)
    -- This is an example from the gksphone esx.lua file
    return Config.Core.GetPlayerFromIdentifier(identifier)
end
```

### GetCharacterName

Returns the character's full name.

```lua
function GetCharacterName(source)
    -- This is an example from the gksphone qb.lua file
    local xPlayer = Config.Core.Functions.GetPlayer(source)
    local name = xPlayer.PlayerData.charinfo.firstname .. ' ' .. xPlayer.PlayerData.charinfo.lastname
    return name
end
```

### GetCharacterBirthDate

Returns the character's birth date.

```lua
function GetCharacterBirthDate(source)
    -- This is an example from the gksphone qb.lua file
    local xPlayer = Config.Core.Functions.GetPlayer(source)
    local date = xPlayer.PlayerData.charinfo.birthdate
    return date
end
```

### GetCharacterAllVehicles

Returns a list of all vehicles owned by a player.

<pre class="language-lua"><code class="lang-lua">---@param source number
---@return vehiclesData[] vehicles An array of vehicles that the player owns
function GetCharacterAllVehicles(identifier, appname)
<strong>    local vehicles = {}
</strong><strong>    -- Example
</strong><strong>    vehiclesData = [
</strong><strong>        {
</strong><strong>            plate = "GKS11111",
</strong><strong>            hash = 1274868363,
</strong><strong>            model = "bestiagts",
</strong><strong>            fuel = 100,
</strong><strong>            engine = 1000,
</strong><strong>            body = 1000,
</strong><strong>            garage = "Garage Name", -- garage name, Out, Impounded, On The Street
</strong><strong>            carseller = 0,
</strong><strong>            name = "Bestia GTS",
</strong><strong>            type = "Car"
</strong><strong>        }
</strong><strong>    ]
</strong><strong>    return vehiclesData
</strong>end
</code></pre>

### GetVehicle

Fetch a specific vehicle using its plate number.

```lua
function GetVehicle(identifier, plate)
    -- Example
    local vehData = {
        plate = "GKS11111",
        hash = 1274868363,
        model = "bestiagts",
        fuel = 100,
        carseller = 0,
        vehMods = {} -- vehicle modification information
    }
    return vehData
end
```

### VehicleUpdate

Updates vehicle status when it's retrieved via valet

```lua
function VehicleUpdate(plate)
    -- This is an example from the gksphone esx.lua file
    if GetResourceState("loaf_garage") == "started" then
        MySQL.Async.execute('UPDATE owned_vehicles SET `stored` = @stored, `parking` = @parking WHERE `plate` = @plate',
            {
                ['@plate'] = plate,
                ['@stored'] = 0,
                ['@parking'] = nil
            })
    elseif GetResourceState("cd_garage") == "started" or GetResourceState("jg-advancedgarages") == "started" then
        MySQL.Async.execute('UPDATE owned_vehicles SET  `in_garage` = @in_garage WHERE `plate` = @plate', {
            ['@plate'] = plate,
            ['@in_garage'] = 0,
        })
    elseif GetResourceState("esx_garage") == "started" then
        MySQL.Async.execute('UPDATE owned_vehicles SET  `stored` = @stored WHERE `plate` = @plate', {
            ['@plate'] = plate,
            ['@stored'] = 0,
        })
    end
end

```

### VehicleUpdateCarseller

Handles vehicle ownership changes made through the Car Seller app.

```lua
function VehicleUpdateCarseller(plate, data, source, identifier)
    -- This is an example from the gksphone esx.lua file
    if data == 1 or data == 0 then
        MySQL.Async.execute('UPDATE owned_vehicles SET `carseller` = @carseller WHERE `plate` = @plate', {
            ['@plate'] = plate,
            ['@carseller'] = data
        })
    else
        local query = string.format(
        'UPDATE owned_vehicles SET `carseller` = @carseller, `owner` = @owner, %s = @garage, %s WHERE `plate` = @plate',
            Config.GarageDBColumn, Config.GarageStored)
        MySQL.Async.execute(query, {
            ['@owner'] = identifier,
            ['@plate'] = plate,
            ['@carseller'] = 0,
            ['@garage'] = Config.GarageDefaultName
        })
    end
end
```

### GetCharacterJob

Retrieves job-related data for the character.

```lua
function GetCharacterJob(source)
    -- This is an example from the gksphone esx.lua file
    local xPlayer = Config.Core.GetPlayerFromId(source) or Config.Core.GetPlayerFromIdentifier(identifier)
    if xPlayer then
        local jobData = {
            source = xPlayer.source,
            identifier = xPlayer.identifier,
            name = xPlayer.job.name,
            label = xPlayer.job.label,
            grade = xPlayer.job.grade,
            grade_salary = xPlayer.job.grade_salary,
            grade_label = xPlayer.job.grade_label,
            grade_name = xPlayer.job.grade_name,
        }
        return jobData
    end
    return nil
end
```

### GetJobs

Returns a list of available jobs in the framework.

```lua
function GetCharacterJob(source)
    -- This is an example from the gksphone qb.lua file
    -- example list
    local jobList = {
	police = {
		label = 'Law Enforcement',
		type = 'leo',
		defaultDuty = true,
		offDutyPay = false,
		grades = {
			['0'] = { name = 'Recruit', payment = 50 },
			['1'] = { name = 'Officer', payment = 75 },
			['2'] = { name = 'Sergeant', payment = 100 },
			['3'] = { name = 'Lieutenant', payment = 125 },
			['4'] = { name = 'Chief', isboss = true, payment = 150 },
		},
	},
	ambulance = {
		label = 'EMS',
		type = 'ems',
		defaultDuty = true,
		offDutyPay = false,
		grades = {
			['0'] = { name = 'Recruit', payment = 50 },
			['1'] = { name = 'Paramedic', payment = 75 },
			['2'] = { name = 'Doctor', payment = 100 },
			['3'] = { name = 'Surgeon', payment = 125 },
			['4'] = { name = 'Chief', isboss = true, payment = 150 },
		},
	},
    }
    
    return Config.Core.Shared.Jobs
end
```

### GetAllEmployees

Fetches a list of employees (online and offline) for a specific job.

```lua
function GetAllEmployees(job)
    -- This is an example from the gksphone qb.lua file
    local query =
    [[SELECT
            JSON_UNQUOTE(JSON_EXTRACT(u.charinfo, '$.firstname')) AS firstname,
            JSON_UNQUOTE(JSON_EXTRACT(u.charinfo, '$.lastname')) AS lastname,
            JSON_UNQUOTE(JSON_EXTRACT(u.job, '$.payment')) AS payment,
            JSON_UNQUOTE(JSON_EXTRACT(u.job, '$.grade.name')) AS gradeLabel,
            JSON_UNQUOTE(JSON_EXTRACT(u.job, '$.grade.level')) AS job_grade,
            u.citizenid AS `identifier`
        FROM players u
        WHERE JSON_UNQUOTE(JSON_EXTRACT(u.job, '$.name')) = ?]]
    local result = MySQL.Sync.fetchAll(query, { job })
    return result
end
```

### SetJob

Updates a player's job and grade.

```lua
function SetJob(identifier, job, grade)
    -- This is an example from the gksphone qb.lua file
    local xPlayer = Config.Core.Functions.GetPlayerByCitizenId(identifier) or
        Config.Core.Functions.GetOfflinePlayerByCitizenId(identifier)
    if xPlayer then
        if xPlayer.Functions.SetJob(job, grade) then
            xPlayer.Functions.Save()
            return true
        end
    end
    return false
end
```

### ToggleDuty

Changes a character's duty status.

```lua
function ToggleDuty(source, toggle)
    -- This is an example from the gksphone esx.lua file
    local xPlayer = Config.Core.Functions.GetPlayer(source)
    if xPlayer then
        xPlayer.Functions.SetJobDuty(toggle)
    end
end
```

### GetBankBalance

Returns the current bank balance of a character.

```lua
function GetBankBalance(source)
    -- This is an example from the gksphone esx.lua file
    local xPlayer = Config.Core.Functions.GetPlayer(source)
    return xPlayer?.PlayerData?.money?.bank or 0
end
```

### GetBankBalanceByIndetifier

Returns the bank balance based on the character's identifier.

```lua
function GetBankBalanceByIndetifier(identifier)
    -- This is an example from the gksphone esx.lua file
    local bank = 0
    local xPlayer = GetPlayerFromIdentifier(identifier)
    if xPlayer then
        bank = xPlayer?.PlayerData?.money?.bank or 0
        return bank
    else
        xPlayer = GetOfflinePlayerByIdentifier(identifier)
        if xPlayer then
            bank = xPlayer?.PlayerData?.money?.bank or 0
            return bank
        end
    end
    return bank
end
```

### RemoveBankMoney

Deducts money from a character's bank account.

```lua
function RemoveBankMoney(source, amount, type)
    -- This is an example from the gksphone esx.lua file
    if type == "identifier" then
        local xPlayer = GetPlayerFromIdentifier(source)
        if not xPlayer or amount < 0 or GetBankBalanceByIndetifier(source) < amount then
            return false
        end
        xPlayer.Functions.RemoveMoney('bank', amount, 'gksphone')
        return true
    else
        local xPlayer = Config.Core.Functions.GetPlayer(source)
        if not xPlayer or amount < 0 or GetBankBalance(source) < amount then
            return false
        end
        xPlayer.Functions.RemoveMoney('bank', amount, 'gksphone')
        return true
    end
end
```

### AddBankMoney

Adds money to a character's bank account.

```lua
function AddBankMoney(source, amount, type)
    -- This is an example from the gksphone qb.lua file
    if type == "identifier" then
        local xPlayer = GetPlayerFromIdentifier(source)
        if not xPlayer or amount < 0 then
            return false
        end
        xPlayer.Functions.AddMoney('bank', amount, "Bank Transfer")
        return true
    end
    local xPlayer = Config.Core.Functions.GetPlayer(source)
    if not xPlayer or amount < 0 then
        return false
    end
    xPlayer.Functions.AddMoney('bank', amount, "Bank Transfer")
    return true
end
```

### GetExtendedPlayers

Returns an array of player sources with a specified job.

```lua
function GetExtendedPlayers(key, val)
    -- This is an example from the gksphone qb.lua file
    local xPlayers = {}
    local players = Config.Core.Functions.GetQBPlayers()
    for _, v in pairs(players) do
        if key then
            if (key == 'job' and v.PlayerData.job.name == val) then
                xPlayers[#xPlayers + 1] = {
                    source = v.PlayerData.source,
                    job = {
                        name = v.PlayerData.job.name,
                        grade = v.PlayerData.job.grade.level
                    }
                }
            end
        end
    end
    return xPlayers
end
```

### RegisterUsableItem

Registers a usable item and sets a callback for when the item is used.

```lua
function RegisterUsableItem(item, cb)
    -- This is an example from the gksphone qb.lua file
    Config.Core.Functions.CreateUseableItem(item, cb)
end
```

### RemoveItem

Removes a specific item from a player's inventory.

```lua
function RemoveItem(source, itemname, amount)
    -- This is an example from the gksphone qb.lua file
    local Player = Config.Core.Functions.GetPlayer(source)
    if Player then
        Player.Functions.RemoveItem(itemname, amount)
    end
end
```

### FreamworkSavePhoneNumber

Saves a player's phone number to the framework's meta or SQL data.

```lua
function FreamworkSavePhoneNumber(phoneNumber, source)
    -- This is an example from the gksphone qb.lua file
    local src = source
    local Player = Config.Core.Functions.GetPlayer(src)
    if Player and phoneNumber then
        Player.PlayerData.charinfo.phone = phoneNumber
        Player.Functions.SetPlayerData('charinfo', Player.PlayerData.charinfo)
    end
end
```

### FreamworkGetPhoneNumberBySource

Retrieves a player's registered phone number.

```lua
function FreamworkGetPhoneNumberBySource(source)
    -- This is an example from the gksphone qb.lua file
    local src = source
    local Player = Config.Core.Functions.GetPlayer(src)
    if Player then
        return Player.PlayerData.charinfo.phone
    end
    return nil
end
```

### HasPhoneItem

Checks if the player has a phone item in their inventory.

```lua
function HasPhoneItem(source)
    -- This is an example from the gksphone qb.lua file
    local src = source
    local Player = Config.Core.Functions.GetPlayer(src)
    local itemData = {}
    if Player then
        for k, _ in pairs(Config.ItemName) do
            local itemCheck = Player.Functions.GetItemsByName(k)
            if itemCheck and #itemCheck > 0 then
                itemData = itemCheck
                break
            end
        end
        if #itemData > 0 then
            return itemData
        end
    end
    return itemData
end

```

### CallingPlayerStatus

Determines if a player is available to receive calls based on handcuff or downed status.

```lua
function CallingPlayerStatus(source)
    -- This is an example from the gksphone qb.lua file
    local retval = false
    local Player = Config.Core.Functions.GetPlayer(source)
    if Player and (Player.PlayerData.metadata["ishandcuffed"] or Player.PlayerData.metadata["isdead"] or Player.PlayerData.metadata["inlaststand"]) then
        retval = true
    end
    return retval
end
```

### GetOfflinePlayerByIdentifier

Returns limited data about an offline player using their identifier.

```lua
function GetOfflinePlayerByIdentifier(identifier)
    local self = {}
    self.accounts = {}
    function self.getAccount(account)
        if self.accounts[account] then
            return {money = self.accounts[account]}
        end
        return nil
    end

    function self.removeAccountMoney(account, amount, reason)
        return true
    end

    function self.addAccountMoney(account, amount, reason)
        return true
    end

    function self.getName()
        return ""
    end

    return self
end
```

## Society (Job System)

### SocietyGetMoney

Returns the amount of money in the job's account.

```lua
function SocietyGetMoney(jobname)
    -- This is an example from the gksphone qb.lua file
    local BusinessMoney = 0
    if GetResourceState("qb-banking") == "started" then
        BusinessMoney = exports['qb-banking']:GetAccount(jobname)?.account_balance or 0
    elseif GetResourceState("Renewed-Banking") == "started" then
        BusinessMoney = exports['Renewed-Banking']:getAccountMoney(jobname) or 0
    end
    return BusinessMoney
end
```

### SocietyRemoveMoney

Deducts money from the job's account, if sufficient funds exist.

```lua
function SocietyRemoveMoney(job, amount)
    -- This is an example from the gksphone qb.lua file
    local process = false
    if GetResourceState("qb-banking") == "started" then
        local jobPrice = SocietyGetMoney(job)
        if jobPrice >= amount then
            if exports['qb-banking']:RemoveMoney(job, amount) then
                process = true
            end
        end
    elseif GetResourceState("Renewed-Banking") == "started" then
        local jobPrice = SocietyGetMoney(job)
        if jobPrice >= amount then
            if exports['Renewed-Banking']:removeAccountMoney(job, amount) then
                process = true
            end
        end
    end
    return process
end
```

### SocietyAddMoney

Adds money to the job's account.

```lua
function SocietyAddMoney(job, amount)
    -- This is an example from the gksphone qb.lua file
    local process = false
    if GetResourceState("qb-banking") == "started" then
        if exports['qb-banking']:AddMoney(job, amount) then
            process = true
        end
    elseif GetResourceState("Renewed-Banking") == "started" then
        if exports['Renewed-Banking']:addAccountMoney(job, amount) then
            process = true
        end
    end
    return process
end
```

> **Note:**
>
> * The code samples provided are from `esx.lua` and `qb.lua`.
> * Replace placeholder logic with implementations based on your framework structure.
> * Ensure all data formats and player handling methods are compatible with your existing systems.
