# 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.


---

# 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://docs.gkshop.org/gksphone-v2/custom-framework/server.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.
