RX Scripts Logo
Billing

Configurables

All config & open sourced files included within this script.

Config Files

--[[
    FREE SCRIPT
    DOWNLOAD @ https://store.rxscripts.xyz/
    SUPPORT @ https://discord.gg/DHnjcW96an
    BY RX Scripts © rxscripts.xyz
--]]

Config = {}

Config.Locale = 'en'

Config.ReceiveMoney = {
    enabled = true, -- When enabled, money from paid invoices go to the sender/society account
    deductTax = 0.05, -- Tax percentage that will be deducted from the invoice amount when paid (0.05 = 5%)
}

Config.PlayerInvoices = { -- Automatic payment is disabled within this feature, so it cannot get abused
    enabled = true, -- Allow players to send invoices to other players
    maxInvoices = 5, -- Maximum number of pending invoices a player can send in total (to prevent spamming)
}

Config.JobInvoices = {
    ['police'] = {
        label = 'Police',
        requiredGrade = 2, -- The minimum grade required to create & pay invoices
        presetInvoices = {
            { name = 'Running Red Light', amount = 250, reason = 'Running Red Light' },
            { name = 'Illegal Parking',   amount = 150, reason = 'Illegal Parking' },
            { name = 'Speeding',          amount = 300, reason = 'Speeding' },
            { name = 'Reckless Driving',  amount = 500, reason = 'Reckless Driving' },
            { name = 'Assault',           amount = 1000, reason = 'Assault' },
        }
    },
    ['ambulance'] = {
        label = 'Ambulance',
        requiredGrade = 2, -- The minimum grade required to create & pay invoices
        presetInvoices = {
            { name = 'Medical Service', amount = 500, reason = 'Medical Service' },
            { name = 'Ambulance Call',   amount = 300, reason = 'Ambulance Call' },
        }
    },
    ['mechanic'] = {
        label = 'Mechanic',
        requiredGrade = 1, -- The minimum grade required to create & pay invoices
        presetInvoices = {
            { name = 'Car Repair', amount = 200, reason = 'Car Repair' },
            { name = 'Towing Service', amount = 300, reason = 'Towing Service' },
        }
    },
    ['taxi'] = {
        label = 'Taxi',
        requiredGrade = 1, -- The minimum grade required to create & pay invoices
        presetInvoices = {
            { name = 'Taxi Service', amount = 100, reason = 'Taxi Service' },
            { name = 'Airport Transfer', amount = 200, reason = 'Airport Transfer' },
        }
    },
}

Config.AutoPay = {
    enabled = true, -- Enable automatic payment of invoices after a certain time of pending
    hours = 24, -- Time in hours after which the invoice will be automatically paid
    feePercentagePerHour = 0.05 -- Percentage of the invoice amount that will be added as a fee for each hour of pending time (0.05 = 5%)
}

Config.Commands = {
    openBilling = 'billing', -- /billing | Open the billing menu
}

Config.Keybinds = {
    openBilling = 'F10', -- Opens the billing menu | Set to false to disable
}

Config.UI = {
    color = {
        primary = { -- Different shades of primary color
            [50] = "#FEDDE9",
            [100] = "#FCBAD3",
            [200] = "#FA76A6",
            [300] = "#F7317A",
            [400] = "#D80955",
            [500] = "#95063B",
            [600] = "#76052E",
            [700] = "#580423",
            [800] = "#3B0217",
            [900] = "#1D010C",
            [950] = "#0F0106"
        },
    }
}

--[[
    ONLY CHANGE THIS PART IF YOU HAVE RENAMED SCRIPTS SUCH AS FRAMEWORK, TARGET, INVENTORY ETC
    RENAME THE SCRIPT NAME TO THE NEW NAME
--]]
---@type table Only change these if you have changed the name of a resource
Resources = {
    FM = { name = 'fmLib', export = 'new' },
    RX_BANKING = { name = 'RxBanking', export = 'all' },
}
IgnoreScriptFoundLogs = false

Opensource Files

All script-related open source code is contained within these files. Third-party components, including frameworks, inventory systems, and other external code, are separately maintained & open sourced in our fmLib repository.
--[[
    FREE SCRIPT
    DOWNLOAD @ https://store.rxscripts.xyz/
    SUPPORT @ https://discord.gg/rxscripts
    BY RX Scripts © rxscripts.xyz
--]]

Config.DiscordWebhooks = {
    invoiceSent = '',
    invoicePaid = '',
    invoiceRevoked = '',
    invoiceDeclined = '',
}

--[[
    We have integrated RxBanking by default, to work with societies.
    If you use any other banking or society accounting system, you can modify the functions below.
    We HIGHLY recommend using RxBanking together with this billing script to ensure the best experience.

    We love that you are using our script, so here is a little easter egg gift for you:
    15% DISCOUNT OFF: Advanced Banking - RxBanking
    CODE: 'FROMBILLING15'

    If you want to use RxBanking, you can find it here:
    https://store.rxscripts.xyz/scripts/advanced-banking
--]]
function RemoveMoneyFromSociety(society, amount)
    if RX_BANKING then
        return RX_BANKING:RemoveSocietyMoney(society, amount, 'payment', 'Invoice Paid')
    end

    Error('RxBanking not found, unable to remove money from society')
    Error('Modify RemoveMoneyFromSociety function in RxBilling/server/opensource.lua to use your own banking system')

    return 0
end

function GetSocietyMoney(society)
    if RX_BANKING then
        local acc = RX_BANKING:GetSocietyAccount(society)
        if acc then return acc.balance end
    end

    Error('RxBanking not found, unable to get money from society')
    Error('Modify GetSocietyMoney function in RxBilling/server/opensource.lua to use your own banking system')

    return 0
end

function AddMoneyToSociety(society, amount)
    if RX_BANKING then
        return RX_BANKING:AddSocietyMoney(society, amount, 'payment', 'Invoice Payment')
    end

    Error('RxBanking not found, unable to add money to society')
    Error('Modify AddMoneyToSociety function in RxBilling/server/opensource.lua to use your own banking system')

    return 0
end

function RemoveMoneyFromBank(identifier, amount)
    if RX_BANKING then
        local personalAcc = RX_BANKING:GetPlayerPersonalAccount(identifier)
        if personalAcc then
            return RX_BANKING:RemoveAccountMoney(personalAcc.iban, amount, 'payment', 'Invoice Paid')
        end
    end

    local table = GetResourceState('es_extended') == 'started' and 'users' or 'players'
    local accountsColumn = GetResourceState('es_extended') == 'started' and 'accounts' or 'money'
    local identifierColumn = GetResourceState('es_extended') == 'started' and 'identifier' or 'citizenid'

    return MySQL.update.await(
        string.format(
            'UPDATE %s SET %s = JSON_SET(%s, "$.bank", JSON_EXTRACT(%s, "$.bank") - @amount) WHERE %s = @identifier',
            table, accountsColumn, accountsColumn, accountsColumn, identifierColumn),
        {
            ['@amount'] = amount,
            ['@identifier'] = identifier,
        }
    )
end

function AddMoneyToBank(identifier, amount)
    if RX_BANKING then
        local personalAcc = RX_BANKING:GetPlayerPersonalAccount(identifier)
        if personalAcc then
            return RX_BANKING:AddAccountMoney(personalAcc.iban, amount, 'payment', 'Invoice Payment')
        end
    end

    local table = GetResourceState('es_extended') == 'started' and 'users' or 'players'
    local accountsColumn = GetResourceState('es_extended') == 'started' and 'accounts' or 'money'
    local identifierColumn = GetResourceState('es_extended') == 'started' and 'identifier' or 'citizenid'

    return MySQL.update.await(
        string.format(
            'UPDATE %s SET %s = JSON_SET(%s, "$.bank", JSON_EXTRACT(%s, "$.bank") + @amount) WHERE %s = @identifier',
            table, accountsColumn, accountsColumn, accountsColumn, identifierColumn),
        {
            ['@amount'] = amount,
            ['@identifier'] = identifier,
        }
    )
end

RegisterNetEvent('rxbilling:onInvoiceSent', function(invoice)

end)

RegisterNetEvent('rxbilling:onInvoicePaid', function(payerId, invoice)
    -- If playerId is nil, it means the invoice was paid automatically
end)

RegisterNetEvent('rxbilling:onInvoiceDeclined', function(declinerId, invoice)

end)

RegisterNetEvent('rxbilling:onInvoiceRevoked', function(revokerId, invoice)

end)