Developers
The lation banking server and client exports with parameters and return values, its events, the server hooks and the open code, with Lua examples.
Every account export takes an account id:
| Account | Id |
|---|---|
| Personal | The player's identifier: citizenid on Qbox and QBCore, identifier on ESX |
| Society | The job or gang name, such as police |
| Shared and savings | The account number, such as LS12345678, or the id it was created with |
| Business | The id the resource that opened it chose |
Whether a player is connected makes no difference to a personal account: it reads and moves the same either way. PayBill is the one export that needs the player online, and only for a bill sent to a player.
A few rules hold for every export:
- The account exports wait until the bank has loaded its accounts before answering, so a resource that starts beside the bank gets real answers, not misses.
- Amounts are whole numbers. Decimals are rounded down, and an amount of zero or less, or above
2000000000, is refused. - Exports skip the checks made for players: transfer limits, the offline-transfer setting, the billing list, the limit of 10 open bills on one account and
Hooks.canTransactapply only to what players do in the bank. The Bills and Requests switches do apply:CreateBillandPayBillrefuse while they are off. - The money exports return a refusal code as their third value when they refuse.
- Money an export moves is written into the history, naming the calling resource as the actor (
PayBillnames the player), and fireslation_banking:transaction.
Server exports
Accounts
GetAccount
Server export
local account = exports.lation_banking:GetAccount(id)Parameters
idstring- Any account id
Returns
table | nil- A copy of the account (below), or
nilwhen there is none, or the id is an offline player the bank has never seen
The account:
{
id = 'police',
type = 'society', -- 'personal', 'savings', 'shared', 'society' or 'business'
name = 'LSPD', -- the display name
number = 'LS88001000', -- the account number, without spaces
balance = 18325,
owner = nil, -- the owner's identifier; the player's own for a personal account
frozen = false, -- frozen by an admin
members = {
{ identifier = 'ABC12345', name = 'Jane Doe', permissions = { deposit = true, withdraw = true, transfer = true, manage = false } },
},
}GetAccountBalance
Server export
local balance = exports.lation_banking:GetAccountBalance(id)Parameters
idstring- Any account id
Returns
number | nil- The balance, or
nilwhen there is no such account. For an offline player it is read from their character record.
local balance = exports.lation_banking:GetAccountBalance('police') or 0GetPlayerAccounts
Server export
local accounts = exports.lation_banking:GetPlayerAccounts(identifier)Parameters
identifierstring- The player's identifier
Returns
table- Every account other than their personal one that the player can use: savings, societies, business and shared accounts
Each entry has the GetAccount fields plus role (owner, member or boss) and, while the player is online, permissions. For an offline player, a society reached through their job or gang can't be seen; a society they were added to by name still shows.
GetAccountMembers
Server export
local members = exports.lation_banking:GetAccountMembers(id)Parameters
idstring- A savings, shared, society or business account id
Returns
table{ identifier, name, permissions }for each member, or an empty table
GetPlayerAccountNumber
Server export
local number = exports.lation_banking:GetPlayerAccountNumber(identifier)Parameters
identifierstring- The player's identifier
Returns
string | nil- The player's personal account number, without spaces, or
nilif the bank has never seen them
GetIdentifierByAccountNumber
Server export
local identifier = exports.lation_banking:GetIdentifierByAccountNumber(number)Parameters
numberstring- A personal account number. Spaces and dashes are ignored.
Returns
string | nil- The identifier behind it, or
nil. Other kinds of account returnnil.
local identifier = exports.lation_banking:GetIdentifierByAccountNumber('LS 1234 5678')Money
Refusal codes
AddAccountMoney, RemoveAccountMoney, TransferMoney and PayBill return false and a code as their third value when they refuse. The second value stays what it always was, so scripts that read it keep working; test the third. A code is the last part of the bank's errors.<code> locale key where there is one, and is never translated.
| Code | What happened | Returned by |
|---|---|---|
invalid | An id that is not a non-empty string | Add, Remove, Transfer |
invalid_amount | Not a positive whole amount within the bank's limit | Add, Remove, Transfer |
database | The bank's accounts did not load | Add, Remove, Transfer |
unknown_account | No account and no character by that id | Add, Remove, Transfer |
recipient_unknown | Nothing found for the target | Transfer |
same_account | The sender and the target are one account | Transfer |
insufficient_funds | The paying side can't cover it | Remove, Transfer, PayBill |
frozen | The paying account is frozen | Remove, Transfer, PayBill |
failed | It did not go through; nothing moved | Add, Transfer, PayBill |
bill_settled | The bill is no longer unpaid | PayBill |
bills_disabled, requests_disabled | That kind is switched off | PayBill |
no_access | The account named can't pay this bill | PayBill |
recipient_offline | A player's bill, and the player is offline | PayBill |
busy | The player is in the middle of another payment | PayBill |
local ok, message, code = exports.lation_banking:TransferMoney('police', 'LS12345678', 1000, 'Consulting')
if not ok and code == 'insufficient_funds' then
-- the police account is short
endAddAccountMoney
Server export
local ok, _, code = exports.lation_banking:AddAccountMoney(id, amount, note)Parameters
idstring- Any account id
amountnumber- The amount to add
notestringoptionaldefaultnil- The history line's description
Returns
boolean, nil, stringtrue, orfalse,niland a refusal code:unknown_accountwhen there is no such account or character,failedwhen the framework refused
Credits the account and writes an income line. On a personal account it moves the framework's bank money, online or not. A frozen account still takes money in.
exports.lation_banking:AddAccountMoney('police', 2500, 'Impound fee')RemoveAccountMoney
Server export
local ok, _, code = exports.lation_banking:RemoveAccountMoney(id, amount, note)Parameters
idstring- Any account id
amountnumber- The amount to take
notestringoptionaldefaultnil- The history line's description
Returns
boolean, nil, stringtrue, orfalse,niland a refusal code, moving nothing:insufficient_fundswhen the balance can't cover it,frozenwhen the account is frozen
Debits the account and writes an expense line.
local ok, _, code = exports.lation_banking:RemoveAccountMoney('mechanic', 900, 'Parts order')
if not ok then
return -- 'insufficient_funds': the society can't pay for it; 'frozen': an admin froze it
endTransferMoney
Server export
local ok, message, code = exports.lation_banking:TransferMoney(fromId, toId, amount, note)Parameters
fromIdstring- The account paying
toIdstring- An account number, account id or player identifier
amountnumber- The amount to send
notestringoptionaldefaultnil- Shown on both history lines. Without one, the lines read
Transfer to <name>andTransfer from <name>.
Returns
boolean, string, stringtrueand the bank's message, orfalse, a message and a refusal code
Moves the money and writes a transfer_out and a transfer_in line under one reference, and tells an online player who received it. Offline recipients are always paid.
On failure the message is invalid, recipient_unknown or same_account when the call is refused before anything is looked up, and the bank's own message in the server's language after that (a frozen sender reads as insufficient funds there). The code says which it was: insufficient_funds, frozen, unknown_account, failed and the rest in the table.
local ok, message, code = exports.lation_banking:TransferMoney('police', 'LS12345678', 1000, 'Consulting')
if not ok then print(('transfer refused: %s (%s)'):format(code, message)) endManaging accounts
CreateAccount
Server export
local account, err = exports.lation_banking:CreateAccount(data)Parameters
data.idstringoptionaldefaulta new account number- Up to 50 characters. Prefix it with your resource name for a business account.
data.typestringoptionaldefault'shared''society','shared','savings'or'business'data.namestring- The display name, up to 40 characters
data.ownerstringoptional- The owner's identifier. Required for savings, ignored for a society.
data.balancenumberoptionaldefault0- The opening balance
Returns
table | nil, string- The account as
GetAccountreturns it, ornilandinvalid,invalid_name,existsordatabase
A player may hold one savings account. The shared-account limit per player doesn't apply here, and business accounts never count against it.
local account, err = exports.lation_banking:CreateAccount({ id = 'myshop:12', type = 'business', name = 'Bean Machine', owner = ownerIdentifier })
if not account then print(('could not open the account: %s'):format(err)) endDeleteAccount
Server export
local ok = exports.lation_banking:DeleteAccount(id)Parameters
idstring- A savings, shared, society or business account id
Returns
boolean
Removes the account and its members.
DeleteAccount does not pay the balance out anywhere. Move it first with TransferMoney or RemoveAccountMoney.
RenameAccount
Server export
local ok = exports.lation_banking:RenameAccount(id, name)Parameters
idstring- The account
namestring- The new display name, up to 40 characters
Returns
boolean
The id never changes. A society's name is set back to its job's label on the next start.
SetAccountFrozen
Server export
local ok = exports.lation_banking:SetAccountFrozen(id, frozen)Parameters
idstring- The account; personal accounts can't be frozen
frozenbooleantrueto freeze,falseto thaw
Returns
boolean
A frozen account takes money in but refuses withdrawals, transfers out and bill payments.
SetAccountOwner
Server export
local ok = exports.lation_banking:SetAccountOwner(id, identifier)Parameters
idstring- A shared or business account
identifierstring | nil- The new owner. A business account may be given
nilwhile it is between owners; a shared account may not.
Returns
booleanfalsefor any other kind of account
A member who becomes the owner stops being a member.
AddAccountMember
Server export
local ok = exports.lation_banking:AddAccountMember(id, identifier, permissions)Parameters
idstring- The account
identifierstring- The player to add, online or not
permissionstableoptionaldefault{ deposit = true, withdraw = true, transfer = true, manage = false }- Any key left out takes its default
Returns
booleanfalsewhen the player is already a member or the owner
manage only means something on a shared account; on society and business accounts members never manage. A player added to a society who isn't one of its bosses uses these permissions.
exports.lation_banking:AddAccountMember('police', identifier, { deposit = true, withdraw = false, transfer = false })UpdateAccountMember
Server export
local ok = exports.lation_banking:UpdateAccountMember(id, identifier, permissions)Parameters
idstring- The account
identifierstring- A member
permissionstable{ deposit, withdraw, transfer, manage }. Keys left out go back to their defaults, so pass all four.
Returns
booleanfalsewhen the player is not a member
RemoveAccountMember
Server export
local ok = exports.lation_banking:RemoveAccountMember(id, identifier)Parameters
idstring- The account
identifierstring- A member
Returns
booleanfalsewhen the player is not a member
ClearAccountMembers
Server export
local ok = exports.lation_banking:ClearAccountMembers(id)Parameters
idstring- The account
Returns
boolean
Removes every member at once, for a business whose staff were all let go.
History
AddTransaction
Server export
local ok = exports.lation_banking:AddTransaction(id, data)Parameters
idstring- Any account id
data.typestringdeposit,withdraw,transfer_in,transfer_out,incomeorexpensedata.amountnumber- The amount moved
data.notestringoptionaldefaultnil- The description, up to 255 characters
data.counterpartystringoptionaldefaultnil- The other side's name
data.counterpartyAccountstringoptionaldefaultnil- The other side's account number
data.actorstringoptionaldefaultthe calling resource- Who made the move, shown in the admin ledger
data.referencestringoptionaldefaultnil- Up to 40 characters
Returns
booleanfalsefor an unknown type or a bad amount
Writes a history line without moving money, for a script that moves the money itself and wants a clear line in the history. When framework tracking already wrote the same move on a personal account in the last 5 seconds (same amount, same direction), that line is filled in instead of a second one being added.
-- the money already left through the framework; give the line its reason
exports.lation_banking:AddTransaction(identifier, { type = 'expense', amount = 400, note = 'Rent · Alta Street 12', counterparty = 'Alta Street Realty' })GetTransactions
Server export
local page = exports.lation_banking:GetTransactions(id, options)Parameters
idstring- Any account id
options.pagenumberoptionaldefault1- The page to read
options.perPagenumberoptionaldefault25- Rows per page, up to 500
options.filters.typestableoptional- A list of types
options.filters.searchstringoptional- Matches the note, counterparty, actor and reference
options.filters.dateFromstringoptionalYYYY-MM-DDoptions.filters.dateTostringoptionalYYYY-MM-DD
Returns
tabletransactions,paginationandsummary(below)
The page:
{
transactions = { -- newest first
{
id = 4512,
type = 'income',
amount = 2500,
balanceAfter = 18325,
note = 'Impound fee',
counterparty = nil,
counterpartyAccount = nil, -- formatted, 'LS 1234 5678'
actor = 'my_impound', -- the player, or the resource that called an export
reference = nil,
createdAt = 1730000000, -- unix seconds
},
},
pagination = { page = 1, perPage = 25, total = 120, totalPages = 5 },
summary = { income = 52000, expense = 31000, net = 21000 }, -- across every matching row
}local page = exports.lation_banking:GetTransactions('police', {
perPage = 10,
filters = { types = { 'income' }, dateFrom = os.date('%Y-%m-%d', os.time() - 7 * 86400) }
})
print(('police took in %d this week'):format(page.summary.income))Bills
CreateBill
Server export
local billId, err = exports.lation_banking:CreateBill(data)Parameters
data.targetstring- Who pays: a player's identifier or account number, or a society, shared or business account by id or number. Not a savings account.
data.amountnumber- The amount owed
data.notestringoptionaldefaultnil- What it is for, up to 255 characters
data.accountstringoptionaldefaultnil- Where the money goes: a society, shared or business id, or a player identifier. Leave it out for a fine that leaves the economy.
data.issuerstringoptionaldefaultthe account's name, or the calling resource- The name shown on the bill
data.issuerIdstringoptionaldefaultnil- The identifier of the player who wrote it. They are told when it is paid or declined, and can cancel it.
data.duenumberoptionaldefaultnow plus Days until due- The due date in unix seconds
Returns
number | nil, string- The bill's id, or
nilandinvalid,bills_disabled,recipient_unknown,same_account,invalid_amountordatabase
A bill from this export needs no society on the billing list and carries no employee cut. While Config > Bills > Bills is off it is refused with bills_disabled, since nobody could see or pay it.
- Sent to a player, they are told when it arrives and can decline it only while Players can decline bills is on.
- Sent to an account (business to business), everyone who may send money from that account sees it under the account's name and pays it from that account. It can always be declined and is never collected automatically.
same_accountmeanstargetandaccountare the same account.
-- a fine for a player
local billId, err = exports.lation_banking:CreateBill({ target = citizenid, amount = 1500, note = 'Speeding', account = 'police' })
-- one business billing another: the mechanics bill the police for a fleet service
local billId, err = exports.lation_banking:CreateBill({ target = 'police', amount = 3200, note = 'Fleet service', account = 'mechanic' })PayBill
Server export
local ok, reason = exports.lation_banking:PayBill(id, accountId)Parameters
idnumber- The bill's id
accountIdstringoptionaldefaultthe player's personal account- An account the player may transfer from. For a bill sent to an account, that account or nothing.
Returns
boolean, string, stringtrueand the bank's message, orfalse, a message and a refusal code
Pays an unpaid bill.
- A player's bill is paid on their behalf, from
accountIdor their personal account. The player must be online. - A bill sent to an account is paid from that account, with nobody online.
The message is a code for a refusal made before paying is tried (bill_settled, bills_disabled, requests_disabled, no_access, frozen, recipient_offline or busy) and the bank's own message after that; the third value is always the code.
-- the police pay the fleet service they were billed
local ok, message, code = exports.lation_banking:PayBill(billId)
if not ok and code == 'insufficient_funds' then print('the police account is short') endCancelBill
Server export
local ok = exports.lation_banking:CancelBill(id)Parameters
idnumber- The bill's id
Returns
booleanfalsewhen it is not unpaid
Cancels an unpaid bill. Nothing is collected, and when it belongs to a repeating series, the series ends.
GetBills
Server export
local bills = exports.lation_banking:GetBills(id, status)Parameters
idstring- The player who owes them, or an account id for what was billed to that account
statusstringoptionaldefaultnilunpaid,paid,declined,cancelledorexpired; all of them when left out
Returns
table- The newest 100 bills and requests (below)
A bill:
{
id = 812,
kind = 'bill', -- 'bill' or 'request'
amount = 1500,
note = 'Speeding',
status = 'unpaid',
reference = '3FA9C2D1-0B7E',
issuer = 'LSPD', -- the name on the bill
issuerId = nil, -- the player who wrote it
accountId = 'police', -- where the money goes; nil for a fine
target = 'ABC12345', -- who pays: a player's identifier, or an account id
createdAt = 1730000000,
dueAt = 1730604800,
paidAt = nil,
commission = 0, -- the employee cut, in percent
sale = nil, -- a register's ticket: { lines, subtotal, tax, taxRate, taxAccount?, note? }
scheduleId = nil, -- the repeating series it belongs to
repeatDays = nil,
}Loans
GetLoan
Server export
local loan = exports.lation_banking:GetLoan(identifier)Parameters
identifierstring- The player
Returns
table | nil- The player's active or defaulted loan, or
nil
{
id = 31,
identifier = 'ABC12345',
name = 'Jane Doe',
principal = 10000, -- borrowed
interest = 10, -- percent
total = 11000, -- to repay
remaining = 7856,
paid = 3144,
installment = 1572, -- per day
termDays = 7,
nextDue = 1730086400, -- unix seconds
missed = 0,
status = 'active', -- 'active' or 'defaulted'
createdAt = 1729900000,
closedAt = nil,
}Register
GetPosProducts
Server export
local products = exports.lation_banking:GetPosProducts(accountId)Parameters
accountIdstring- The business's society id
Returns
table- The menu in order:
{ id, category, label, price, item }each. A price of0means on the menu but not for sale.
AddPosProduct
Server export
local productId, err = exports.lation_banking:AddPosProduct(accountId, data)Parameters
accountIdstring- The business's society id
data.labelstring- The product name, up to 40 characters
data.pricenumber- Above zero
data.categorystringoptionaldefaultnil- Up to 30 characters
data.itemstringoptionaldefaultnil- An inventory item name, for the tile's picture
Returns
number | nil, string- The product id, or
nilandinvalid,limit(300 products) ordatabase
A register only sells from the menu of a society listed under Config > POS > Businesses. Open registers refresh at once.
exports.lation_banking:AddPosProduct('burgershot', { label = 'Bleeder', price = 12, category = 'Burgers', item = 'burger' })RemovePosProduct
Server export
local ok = exports.lation_banking:RemovePosProduct(id)Parameters
idnumber- The product id
Returns
boolean
Societies and registers
For a resource that runs jobs or businesses of its own, such as lation jobs: society accounts on demand, and register entries under Config > POS that it keeps itself.
EnsureSocietyAccounts
Server export
local ok, reason = exports.lation_banking:EnsureSocietyAccounts(name)Parameters
namestringoptionaldefaultnil- A job or gang name, to ask about that one
Returns
boolean, stringtrue, orfalseandsocieties_disabled,gangs_disabled,unknown_group,invalidordatabase
Does what the bank does on its own start: every job the framework knows gets its society account, and every gang while Config > Accounts > Gang accounts too is on. Safe to call any time; nothing is ever closed, and an account outlives the job it was opened for.
- Without a name it returns
true, orfalse, 'societies_disabled'while Config > Accounts > Society accounts is off, when the bank opens none. - With a name it says whether that account exists afterwards:
true(one opened before society accounts went off still counts), orfalseandsocieties_disabled,gangs_disabled(a gang, with gang accounts off) orunknown_group(a name the framework doesn't know).
Call it after adding a job while the server runs. The bank also does this on its own when lation_jobs:jobCreated or lation_jobs:jobDeleted fires, and on QBCore when qb-core's AddJob or AddGang adds one.
local ok, reason = exports.lation_banking:EnsureSocietyAccounts('tequilala')
if not ok then print(('no society account for tequilala: %s'):format(reason)) endSetPosBusiness
Server export
local ok = exports.lation_banking:SetPosBusiness(id, rules)Parameters
idstring- The society: a job or gang name
rules.taxnumber | falseoptional- Its own sales tax in percent;
falsefor the section's rules.accountstring | falseoptional- The society its tax is paid into;
falsefor the section's rules.lockedbooleanoptionaltruekeeps the menu to the admin: its bosses can't edit it at the register
Returns
booleantrueonce saved, or when nothing needed changing;falsefor a bad argument or a failed save
Lists the society under Config > POS > Businesses, as an admin adding it would, so it gets a register; pass nil instead of rules to take it off. Its menu is kept either way.
It merges: only the fields you pass change, so the tax, tax account and menu setting an admin chose stay when you leave them out, and a resource that lists its businesses on every start never resets them. A new entry starts on the section's tax and account, with the menu open to its bosses. Any other key, such as a label, is ignored.
exports.lation_banking:SetPosBusiness('burgershot', {}) -- give Burger Shot a register
exports.lation_banking:SetPosBusiness('burgershot', nil) -- and take it awaySetPosLocation
Server export
local ok = exports.lation_banking:SetPosLocation(id, point)Parameters
idstring- An id of your own, prefixed with your resource name
point.labelstring- The point's name, up to 40 characters
point.coordstable{ x, y, z, w }point.businessstringoptionaldefault''- The society whose staff see Open register there; empty for any business
Returns
booleantrueonce saved
Places a register point under Config > POS > Registers, replacing the one that id already holds; pass nil instead of point to remove it. The points an admin placed from the panel carry no id and are not yours to change. The 50-point limit counts every point.
exports.lation_banking:SetPosLocation('myjobs:14', { label = 'Counter', business = 'burgershot', coords = { x = -1194.2, y = -893.5, z = 13.9, w = 305.0 } })Players
OpenBank
Server export
local sent = exports.lation_banking:OpenBank(source, kind)Parameters
sourcenumber- The player's server id
kindstringoptionaldefault'bank'bank,atm,bill,posoradmin
Returns
booleantrueonce the request is sent;falseforadminand a player who is not an admin
The usual checks still apply when it opens, such as Hooks.canOpen, the PIN at an ATM, and having a register for pos.
exports.lation_banking:OpenBank(source, 'atm')RequestPin
Server export
local passed = exports.lation_banking:RequestPin(source, accountId)Parameters
sourcenumber- The player's server id
accountIdstringoptionaldefaultnil- A shared or business account; the player's own PIN when left out
Returns
boolean- Whether the player entered the right PIN
Puts something of your own behind the bank's PIN. The player sees the PIN pad and the call waits for the answer, which is decided on the server.
- Returns
truestraight away when Config > ATMs > Ask for a PIN is off or the account has no PIN, so you can always call it and let the server's setting decide. - Returns
falsewhen the player cancels, runs out of tries, already has the bank open, or leaves, and for an unknownaccountId. - Three misses lock the account out for 15 minutes, as at an ATM.
if exports.lation_banking:RequestPin(source) then
OpenTheSafe(source)
endSettings
GetConfig
Server export
local section = exports.lation_banking:GetConfig(name)Parameters
namestringoptionaldefaultnilgeneral,currency,amounts,banks,blip,atm,accounts,transfers,transactions,bills,requests,pos,savingsorloans
Returns
table | nil- A copy of that section, nested by the keys on the configuration page, or every section when left out.
nilfor an unknown section orlogs.
Coordinates come back as { x, y, z, w } tables. Logging is never returned, so the webhook stays on the server.
local atm = exports.lation_banking:GetConfig('atm')
print(atm.pin) -- falseBusiness accounts
A business account holds money for your resource: a player-owned shop, a garage, anything with a till that is not a job. Your resource opens it, names its owner and staff, and moves its money; the bank keeps the balance, the number, the PIN and the history, and players see it under Business accounts.
local id = ('myshop:%s'):format(shopId)
exports.lation_banking:CreateAccount({ id = id, type = 'business', name = 'Bean Machine', owner = ownerIdentifier })
exports.lation_banking:AddAccountMember(id, employeeIdentifier, { deposit = true, withdraw = false, transfer = false })
-- a sale at your till
exports.lation_banking:AddAccountMoney(id, 250, 'Order #1042')
-- the shop changes hands, or nobody owns it for now
exports.lation_banking:SetAccountOwner(id, newOwnerIdentifier)
exports.lation_banking:SetAccountOwner(id, nil)The owner can deposit, withdraw and transfer; members can do what you allowed. Nothing about the account is managed from the bank: players can't rename it, change its members or close it. Business accounts don't count against the shared account limit.
To keep your own copy of the balance in step, listen for lation_banking:transaction and skip the moves your resource made itself.
Client exports
openBank, openATM, openPos and closeBank
Client export
exports.lation_banking:openBank(account) -- the full bank, on that account
exports.lation_banking:openATM() -- the ATM view
exports.lation_banking:openPos() -- the register
exports.lation_banking:closeBank() -- closes whichever is openThey go through the server's checks, as a branch or an ATM does. openBank takes an optional account id: the bank opens on that account when the player can use it, and on their own otherwise; lation jobs' Open in bank uses it. openPos is what the ox_inventory item's client.export calls.
isOpen
Client export
local open = exports.lation_banking:isOpen()Returns
boolean- Whether the bank, an ATM, a card or the admin panel is open
requestPin (client)
Client export
local passed = exports.lation_banking:requestPin(accountId)Parameters
accountIdstringoptionaldefaultnil- A shared or business account; the player's own PIN when left out
Returns
boolean- The server's answer, as
RequestPingives it
if exports.lation_banking:requestPin() then
OpenLocker()
endEvents
lation_banking:transaction
Server event
AddEventHandler('lation_banking:transaction', function(tx) end)Fields of tx
accountIdstring- The account the line is on
typestringdeposit,withdraw,transfer_in,transfer_out,incomeorexpenseamountnumber- Always positive
balanceAfternumber | nil- The balance after the move, when known
notestring | nil- The description
counterpartystring | nil- The other side's name
counterpartyAccountstring | nil- The other side's account number
actorIdentifierstring | nil- The player behind it, when a player acted
actorNamestring | nil- That player's name, or the resource that called an export
referencestring | nil- Shared by both lines of a transfer, and by every line a bill payment writes
A local server event fired for every line the bank writes: player actions, exports, the compatibility exports, other scripts' tracked moves, interest, imports and admin adjustments. A report that fills in a line framework tracking already wrote does not fire it again.
AddEventHandler('lation_banking:transaction', function(tx)
if tx.accountId ~= myAccountId then return end
if tx.actorName == GetCurrentResourceName() then return end -- our own move
print(('%s %d, balance now %s'):format(tx.type, tx.amount, tx.balanceAfter))
end)lation_banking:configUpdated
Server event
AddEventHandler('lation_banking:configUpdated', function(section) end)Parameters
sectionstring | nil- The section an admin saved, such as
atm;nilonce the stored configuration is first loaded on start
A local server event fired after a section is saved and applied. Read the new values with GetConfig.
AddEventHandler('lation_banking:configUpdated', function(section)
if section == 'currency' then
local currency = exports.lation_banking:GetConfig('currency')
print(('the bank now writes money with %s'):format(currency.symbol))
end
end)On the client, lation_banking:configUpdated fires with no arguments when a section the client holds (General, Currency, Quick amounts, Branches, Map blip, ATMs or POS) changed.
Compatibility events
The events the old banks used still work; see Migrating.
| Event | Side | What lation banking does |
|---|---|---|
Renewed-Banking:client:openBankUI | Client | Opens the bank, or the ATM view with { atm = true } |
Renewed-Banking:client:sendNotification | Client | Shows the message as a notification |
okokBanking:OpenATM | Client | Opens the ATM view |
okokBanking:AddNewTransaction | Server, local | Writes both sides of a transfer another script made |
Hooks
server/utils/hooks.lua ships open. Edit the functions in place.
canOpen
Hook
function Hooks.canOpen(source, kind)Parameters
sourcenumber- The player
kindstringbank,atm,bill,pos(a cashier's register),pos_charge(the card a customer pays a sale on) orpin(aRequestPincard)
Returns
boolean, stringfalseand an optional message to refuse
Called before the bank opens. The admin panel does not pass through it.
-- ATMs only for players with a bank card (ox_inventory)
function Hooks.canOpen(source, kind)
if kind == 'atm' and exports.ox_inventory:Search(source, 'count', 'bank_card') < 1 then
return false, 'You need your bank card'
end
return true
endcanTransact
Hook
function Hooks.canTransact(data)Parameters
data.sourcenumber- The player
data.actionstringdeposit,withdraw,transfer,billorposdata.accountIdstring- For
depositandwithdraw, the account; fortransfer, the sender; forbill, the paying account (cashwhen a sale is paid in cash); forpos, the business ringing the sale data.amountnumber- The amount
data.targetstring | nil- For
transfer, the recipient; forbill, the account the bill pays into; forpos, the customer, or the account the sale is billed to
Returns
boolean, stringfalseand an optional message to refuse
Called before a player's deposit, withdrawal, transfer, bill payment or sale, while nothing has moved yet. For a sale the bill does not exist yet, which makes this the place to refuse one whose goods the customer could not carry. Exports, the compatibility exports, loans and ongoing payments do not call it.
function Hooks.canTransact(data)
if data.action == 'withdraw' and data.amount > 50000 then
return false, 'Withdrawals over $50,000 need a manager'
end
return true
endonTransaction
Hook
function Hooks.onTransaction(transaction)Parameters
transactiontable- The same fields as
lation_banking:transaction
Called after every line is written, just before the event fires.
onAccountChange
Hook
function Hooks.onAccountChange(data)Parameters
data.actionstringcreated,deleted,memberAdded,memberUpdatedormemberRemoveddata.accountIdstring- The account
data.sourcenumber- The player who did it
data.identifierstring | nil- The member, for the member actions
Called when a player opens or closes a shared or savings account, or adds, changes or removes a member, including leaving on their own. Changes made through exports do not call it.
function Hooks.onAccountChange(data)
if data.action == 'memberAdded' then
print(('%s was given access to %s'):format(data.identifier, data.accountId))
end
endongoingPayments
Hook
function Hooks.ongoingPayments(source, identifier)Parameters
sourcenumber- The player
identifierstring- Their identifier
Returns
table- A list of entries (below), drawn under the bills
What the player owes other resources, listed under their bills. Called when the Bills page opens, while bills are on, and cached for 30 seconds, so keep it quick. Up to 20 rows are shown, and an error in it is printed to the console instead of breaking the page.
| Field | Type | Default | Description |
|---|---|---|---|
id | string | required | Stable and unique, such as finance:7XD863HX |
label | string | required | The headline |
note | string | nil | The second line |
amount | number | nil | The next payment, shown on the right |
remaining | number | nil | Still owed in all, shown under the amount |
dueAt | number | nil | Unix seconds; shown as a date, red once past |
progress | table | nil | { paid = 1, total = 12 } draws a meter |
icon | string | nil | A name from the bank's icon set, such as car or receipt |
warning | boolean | false | Marks the row as having a problem |
payable | boolean | false | Shows a Pay button; needs pay |
pay | function | nil | pay(source) moves the money itself and returns success, message? |
reason | string | the label | What the history line is called once paid |
pay runs under the player's lock, like every money action, and not at an ATM. Its money leaves through the framework, so with tracking on the line it writes is renamed to reason.
function Hooks.ongoingPayments(source, identifier)
local list = {}
-- ...keep the jg-dealerships block that ships here...
list[#list + 1] = {
id = 'rent:' .. identifier,
label = 'Apartment rent',
note = 'Alta Street 12',
amount = 400,
dueAt = os.time() + 3 * 86400,
icon = 'receipt',
payable = true,
pay = function(src) return PayRent(src) end
}
return list
endOpen code
These files ship unescrowed, for you to edit:
| File | What it holds |
|---|---|
bridge/server.lua, bridge/client.lua | Framework access: players, money, jobs, gangs, HasSocietyAccess, usable items. Add a framework where it says Add custom framework here. |
server/utils/hooks.lua | The hooks above |
server/utils/perms.lua | IsAdmin, who may open /bankadmin |
server/utils/logging.lua | Logging to Discord or Fivemanage, and the logging defaults |
server/database/queries.lua, schema.sql, migrations.lua | Every SQL statement, the tables and the schema updates |
client/utils/interact.lua | Interaction systems, with a custom slot |
client/utils/notify.lua | Notification systems, with a custom slot |
client/utils/peds.lua | How branch peds are spawned |
locales/*.json | Every string |
Still stuck? Ask in our Discord: the people who write the scripts answer.
Last updated