ESX
Dependencies
ox_target or other target with identical format as ox_target (not guaranteed to work)
Installlation
Place the
ylean_loans
folder into your server'sresources
directory.Import
sql.sql
into your MySQL database.
Config File
--Framework settings
ESX = exports["es_extended"]:getSharedObject()
Ylean = {}
Ylean.Debug = false
Ylean.Locales = "en"
Ylean.TargetResource = 'ox_target' -- 'ox_target' support available (you can try other if there is the same syntax as ox_target it should work)
-- Framework events
Ylean.NotifyEvent = 'esx:showNotification' --Client side only event
Ylean.JobUpdateEvent = 'esx:setJob' --Client side only event
Ylean.OnPlayerLoadedEvent = 'esx:playerLoaded' --Client side only event
Ylean.SocietyAccountEvent = 'esx_addonaccount:getSharedAccount' -- server side event
Ylean.OpenClothingMenu = 'esx_skin:openSaveableMenu' -- Boss menu clothing menu [client sided event]
Ylean.DefaultDuty = true -- if set to 'true', player will be on duty after loading in to server
-- GENERAL SETTINGS
Ylean.General = {
blip = {
active = true,
coords = vector4(233.67, 221.3, 113.86, 338.37),
type = 409, -- https://docs.fivem.net/docs/game-references/blips/
text = "Viva Capital",
color = 2 -- https://docs.fivem.net/docs/game-references/blips/#blip-colors
},
floatingEmblem = {
active = true,
coords = { vector3(233.67, 221.3, 113.00), vector3(246.81, 209.6, 113.00), vector3(241.21, 211.66, 113.00)},
type = 29, -- Marker type: https://docs.fivem.net/docs/game-references/markers/
color = {0, 255, 0, 255}, -- RGBA: green color
waveEnabled = true, -- Enable or disable waving
waveAmplitude = 0.2, -- Amplitude of the wave (height of the oscillation)
waveSpeed = 2 -- Speed of the wave
},
ped = {
active = true,
coords = vector4(233.57, 220.39, 109.28, 352.01),
model = "s_m_m_movprem_01", -- https://docs.fivem.net/docs/game-references/ped-models/
animation = {
dict = "amb@world_human_hang_out_street@female_arms_crossed@idle_a", -- Animation dictionary for an idle pose
name = "idle_a", -- Animation name for a relaxed, crossed arms stance
flag = 49 -- Loop the animation, prevent movement
},
waveToPlayer = {
active = true,
distance = 5.0,
animation = {
dict = "gestures@m@standing@casual", -- Animation dictionary
name = "gesture_hello", -- Animation name
flag = 48 -- Prevents movement while waving
}
}
},
menu_open_points = {
debug = false,
coords = { vector3(233.67, 221.3, 111.5), vector3(246.81, 209.6, 111.5), vector3(241.21, 211.66, 111.5)},
accessDistance = 5.0,
icon = "fa-solid fa-right-to-bracket"
}
}
-- JOB SETTINGS
Ylean.BrokerJob = {
name = "financial",
rejectionReasonLength = 200, -- Max. 500 chars
grades = {
['0'] = {
canGrantBusinessLoans = false, -- A variable defining whether an employee with a given rank is allowed to grant business loans
canGrantLoansToPlayers = true, -- A variable defining whether an employee with a given rank is allowed to grant individual loans
individualProfitFromInterest = 30, -- A variable defining the percentage of the interest rate that an employee receives for granting a indiviudal loan
businessProfitFromInterest = 35 -- A variable defining the percentage of the interest rate that an employee receives for granting a business loan
},
['1'] = {
canGrantBusinessLoans = true,
canGrantLoansToPlayers = true,
individualProfitFromInterest = 45,
businessProfitFromInterest = 50
},
['2'] = {
canGrantBusinessLoans = true,
canGrantLoansToPlayers = true,
individualProfitFromInterest = 70,
businessProfitFromInterest = 80
},
},
on_off_duty = {
marker = {
active = true,
coords = vector3(262.98, 209.39, 112.00),
type = 20,
color = {
r = 255,
g = 215,
b = 0,
a = 100
}
},
target = {
active = true,
coords = vector4(262.9, 209.4, 110.29, 346.69),
icon = "fa-solid fa-sign-in-alt",
debugPoly = false,
distance = 2.0
}
},
boss_menu = {
coords = vector4(262.16, 205.88, 109.48, 320.02),
hire_distance = 20.0,
target = {
debug = false,
target_icon = "fas fa-sign-in-alt",
distance = 2.0
}
}
}
-- INDIVIDUAL LOAN SETTINGS
Ylean.IndividualLoan = {
approval = {
active = true, -- If enabled, loans exceeding a certain amount will require mandatory approval from authorized employees
from = 10000000 -- Loans exceeding this amount will require approval from an authorized employee (provided that active = true). If set to "0", every loan will require approval
},
minimumLoanAmount = 1200,
maximumDeadline = 60,
interestRate = {
--[[
If "constant" set to true, regardless of the repayment term chosen by the player, the interest rate will always remain the same (the "value" variable below).
If set to false, the minimum interest rate for a one-day repayment term will be the percentage set in the "min" variable, while the maximum rate
will be the percentage set in the "max" variable below.
]]--
constant = false,
value = 12.5,
min = 5,
max = 15
},
creditScoreGrantedForRepayment = 1,
loanPurposeLength = 150, -- in characters (max. 500)
delay = 15, -- The time that must pass from the full repayment of the loan until the possibility of taking another one. (IN MINUTES)
methodOfGrantingLoan = "bank" -- "bank" or "money"
}
-- INDIVIDUAL LOAN REPAYMENT SETTINGS
Ylean.IndividualLoanRepayment = {
creditScoreLostInCaseOfDelay = 5,
notifyAboutUpcomingRepayment = {
active = true, -- If set to true, the player will be notified about the upcoming installment payment
hours = 30 -- How many hours before the payment due date should the player be notified
},
immediateDeduction = false, -- If true, the loan amount will be immediately deducted from the account once the deadline is passed
interestRate = 0.05, -- Daily interest rate (e.g., 5%)
daysBeforeDeduction = 3 -- Number of days after the deadline before funds are automatically deducted when interest accrues
}
-- BUSINESS LOAN SETTINGS
Ylean.BusinessLoan = {
minimumLoanAmount = 50000,
maximumLoanAmount = 100000,
maximumDeadline = 120,
interestRate = {
--[[
If "constant" set to true, regardless of the repayment term chosen by the player, the interest rate will always remain the same (the "value" variable below).
If set to false, the minimum interest rate for a one-day repayment term will be the percentage set in the "min" variable, while the maximum rate
will be the percentage set in the "max" variable below.
]]--
constant = false,
value = 12.5,
min = 5,
max = 15.5
},
methodOfGrantingLoan = "bank" -- "bank" or "money"
}
-- BUSINESS LOAN REPAYMENT SETTINGS
Ylean.BusinessLoanRepayment = {
notifyAboutUpcomingRepayment = {
active = true, -- If set to true, the player will be notified about the upcoming installment payment
hours = 30 -- How many hours before the payment due date should the player be notified
},
immediateDeduction = true, -- If true, the loan amount will be immediately deducted from the account once the deadline is passed
interestRate = 0.05, -- Daily interest rate (e.g., 5%)
daysBeforeDeduction = 3 -- Number of days after the deadline before funds are automatically deducted when interest accrues
}
-- CREDIT SCORE SETTINGS
Ylean.CreditScore = {
{from = 0, to = 5, max = 5000}, -- Players with a credit score between 0 and 5 can borrow up to 5000
{from = 6, to = 9, max = 10000}, -- Players with a credit score between 6 and 9 can borrow up to 10000 ...
{from = 10, to = 15, max = 15000},
{from = 16, to = 20, max = 20000},
{from = 21, to = 25, max = 35000},
{from = 26, to = 30, max = 50000},
}
Ylean.BossStash = {
id = 'financial_stash',
label = 'Financial Stash',
slots = 50,
weight = 100000,
owner = false,
jobs = 'financial'
}
-- LOCALES INITIALIZE !!DON'T TOUCH!!
function Translate(key)
local languageCode = Ylean.Locales or "en"
local localesTable = _G["Locales_" .. languageCode]
if not localesTable then
localesTable = _G["Locales_en"]
end
return localesTable and localesTable[key] or key
end
function Debug(message)
if Ylean.Debug then
print("[Debug] " .. message)
end
end
Job Settings
The Ylean.BrokerJob
table defines the core settings for the “financial” job (the broker role). Any change in this section—both the name
field and any modifications to the grades
table—must be mirrored in your server’s main job configuration.
Ylean.BrokerJob = {
-- Unique job identifier; must match your main job config
name = "financial",
-- Permissions and profit settings per grade
grades = {
['0'] = {
canGrantBusinessLoans = false, -- allows granting business loans
canGrantLoansToPlayers = true, -- allows granting personal loans
individualProfitFromInterest = 30, -- % of interest the employee earns on personal loans
businessProfitFromInterest = 35 -- % of interest the employee earns on business loans
},
['1'] = {
canGrantBusinessLoans = true,
canGrantLoansToPlayers = true,
individualProfitFromInterest = 45,
businessProfitFromInterest = 50
},
['2'] = {
canGrantBusinessLoans = true,
canGrantLoansToPlayers = true,
individualProfitFromInterest = 70,
businessProfitFromInterest = 80
},
},
}
Configuration Requirements
name
Must exactly match the job name defined in your main configuration file.grades
Each key ('0'
,'1'
,'2'
, etc.) must correspond to a grade defined in that same configuration. Any addition, removal, or renumbering of grades here must be applied to the main job config as well.
Boss Menu Access
Any player whose grade_name
contains the substring "boss"
is granted access to the Boss Menu for the “financial” job.
Interest Rate Settings
Both Business Loans and Individual Loans use the same interestRate
configuration block. It controls how the loan’s interest rate is chosen based on whether you want a fixed rate or a rate that changes with the repayment period.
interestRate = {
constant = <boolean>,
value = <number>, -- only used if constant = true
min = <number>, -- used when constant = false, for the shortest term (1 day)
max = <number> -- used when constant = false, for the longest term
}
1. Fixed Rate Mode (constant = true
)
constant = true
)Behavior No matter what repayment term the player picks, the interest rate is always equal to
value
.Configuration
constant = true
value = 12.5 -- example: always 12.5% interest
-- min and max are ignored

2. Variable Rate Mode (constant = false
)
constant = false
)Behavior
For a 1-day loan, use the
min
rate.For a loan at the maximum allowed deadline (defined by
maximumDeadline
), use themax
rate.For any term in between, interpolate linearly between
min
andmax
.
Linear interpolation formula

Configuration
constant = false min = 5 -- example: 5% for a 1-day loan max = 15.5 -- example: 15.5% for the longest loan term -- value is ignored

Translation Guide
This section explains how to add or edit translations for ylean_loans, covering both the NUI (front-end) and server (back-end) locales, as well as the main NUI HTML file.
1. NUI (Front-End) Translations
Directory:
ylean_loans/nui/locales/
Contains pre-translated JSON files, e.g.en.json
,pl.json
, etc.Add or Edit a Language
Create or modify
your_lang.json
in that folder.{ "unkwnPlayer": "Unknown Player", "welcome": "Welcome", "yourcreditscore": "Your Credit Score", "hire_btn_txt": "HIRE", "employee_of_the_month": "Employee of the Month", "grant_business_loan": "GRANT BUSINESS LOAN", "no_data": "No Data", /* …other keys… */ }
Open
ylean_loans/nui/index.js
. Find the line:let selectedLanguage = "en";
and add or change the code to your filename (without
.json
):let selectedLanguage = "your_lang";
2. Server (Back-End) Translations
Directory:
ylean_loans/locales/
Contains Lua locale files, e.g.en.lua
,pl.lua
, etc.Add or Edit a Language
Create or modify
yourLang.lua
in that folder.
Locales_yourLang = {
LOAN_GRANTED = "Loan Granted",
LOAN_REPAID = "Loan Repaid",
LOAN_DEFAULTED_COLLECTED = "Loan Defaulted - Collected",
LOAN_REJECTED = "Loan Rejected",
LOAN_PENDING = "Pending acceptance",
-- …other keys…
}
Open
config.lua
. Find theYlean.Locales
table and add your filename (without.lua
):
Ylean.Locales = "en"
3. Main NUI HTML
File:
ylean_loans/nui/index.html
Contains static text (headings, placeholders) that may need translation beyond what your JSON files cover.Edit for Your Language
Open
index.html
.Translate any hard-coded strings
Restart script
With these steps, you can fully localize ylean_loans in both the UI and server logic. Remember to keep your filenames (without extensions) consistent when referencing them in index.js
and config.lua
.
Changing the Displayed Currency
To switch the currency symbol shown throughout ylean_loans, update three places: the back-end Lua locales, the NUI JSON locales, and the NUI script.
Back-End (Lua Locales)
Open the appropriate file in
ylean_loans/locales/
(e.g.en.lua
,pl.lua
).Locate any entries containing the currency symbol (for example a key like
insufficientCreditScore = "Insufficient credit score for a $%d loan! Max allowed: $%d"
or inline strings).Replace
"$"
with your desired symbol (e.g."€"
).Save and restart the resource to apply changes.
Front-End NUI (JSON Locales)
Open the corresponding JSON file in
ylean_loans/nui/locales/
(e.g.en.json
,pl.json
).Find any keys or values that include the currency symbol (for example
"validate_repayment_range": "Repayment Amount must be between $"
).Replace
"$"
with your desired symbol.Save the file and reload the NUI to see the updated labels.
Front-End NUI Script
Open
ylean_loans/nui/index.js
.Find the line:
const currency = "$";
Change it to your new symbol, for example:
const currency = "€";
Save the file and reload the script (e.g., via
ensure ylean_loans
).
After completing these three steps, all monetary values and labels in both the UI and server logic will use your new currency symbol.
Changing the Date Format
To adjust how dates are displayed in the NUI:
Open
ylean_loans/nui/index.js
.Locate the line:
const date_format = "en-US";
Replace
"en-US"
with any valid ECMAScript Intl locale string—for example:const date_format = "en-GB"; // DD/MM/YYYY const date_format = "pl-PL"; // DD.MM.YYYY const date_format = "de-DE"; // DD.MM.YYYY with German month names
Save the file and reload the script (e.g., via
ensure ylean_loans
).
The UI will now format all dates according to your chosen locale.
Upcoming Repayment Notification Mechanism
The reminder system alerts borrowers as their payment deadline approaches:
Activation: Controlled by
notifyAboutUpcomingRepayment.active
in each loan’s configuration namespace (IndividualLoanRepayment
orBusinessLoanRepayment
).Threshold: Defined by
notifyAboutUpcomingRepayment.hours
—reminders start when the time until the deadline is less than or equal to this value.Frequency: Once the threshold is reached, borrowers receive a notification every hour until they either repay the loan or the deadline passes and the deduction or interest-accrual procedure is triggered.
To configure:
Enable or disable reminders with the
active
flag.Set the
hours
value to determine how far in advance hourly reminders begin.
Immediate Deduction Mode
In this mode, once the repayment deadline passes, the system automatically deducts the full outstanding balance from the borrower’s bank account. This applies to both individual and business loans, subject to the following configuration:
Enable/Disable: Controlled by the
immediateDeduction
flag in each loan’s settings.Credit Score Penalty (individual loans only): If enabled, a fixed number of credit score points (
creditScoreLostInCaseOfDelay
) is deducted when the funds are collected.Notification: Upon deduction, a log entry and optional webhook notification (e.g., Discord) inform administrators and the borrower of the action.
All related configuration options are defined within the Ylean.IndividualLoanRepayment
and Ylean.BusinessLoanRepayment
namespaces.
Configuration Steps:
Set
immediateDeduction = true
to activate this mode.(Individual loans) Define
creditScoreLostInCaseOfDelay
to apply penalties for delayed repayment.
Interest Accrual Mode
This mode gradually increases the loan amount by a daily interest rate, providing a grace period before enforcing a full deduction:
Interest Accrual: The outstanding principal is multiplied by
(1 + interestRate)
once per day, compounding until collection.Grace Period: A configurable number of days (
daysBeforeDeduction
) gives borrowers time to repay without immediate loss of funds.Final Collection: After the grace period, the total accumulated balance (principal plus accrued interest) is deducted in full. Individual loans may also incur a credit score penalty at this point.
All related configuration options are defined within the Ylean.IndividualLoanRepayment
and Ylean.BusinessLoanRepayment
namespaces.
Configuration Steps:
Set
immediateDeduction = false
to use interest accrual.Define
interestRate
(daily rate) anddaysBeforeDeduction
(grace period).(Individual loans) Optionally configure
creditScoreLostInCaseOfDelay
for score penalties upon final collection.
Comparison of Modes
Activation
immediateDeduction = true
immediateDeduction = false
Interest before deduction
None
Accrued daily until the threshold
Status change
Immediately upon delay
After daysBeforeDeduction
days overdue
Funds deducted
Full principal
Accumulated principal + interest
Credit score impact
Individual loans only
Individual loans only
Discord Webhook Logging
Key loan events can be logged to Discord via webhooks, with each action configurable individually under the YleanDC.Logs
namespace in discord_logs_cfg.lua
file.
Global Settings (YleanDC
):
ServerName
(string): Name of the server displayed in the embed footer.DefaultEmbedColor
(integer): Default color code used for embeds when an event-specific color is not provided.
Per-Event Configuration: Each event under YleanDC.Logs
supports:
Enabled (boolean): Turn logging on or off.
WebhookURL (string): Discord webhook endpoint for that event.
BotName (string) and BotAvatar (string URL): Identity of the webhook bot.
Embed (object): Customization of the embed’s
Title
,Color
, andThumbnail
.
Configured Events:
LoanIndividualNoApproval
Player applied for an individual loan that does not require approval
LoanIndividualApproval
Player applied for an individual loan that requires approval
PartialLoanRepayment
Player made a partial repayment on a loan
FullLoanRepayment
Player fully repaid a loan
SubmitBusinessLoan
Employee submitted a business loan
AcceptBusinessLoan
Player accepted a business loan
RejectBusinessLoan
Player rejected a business loan
OverdueLoanIndividual
Player failed to repay an individual loan on time
OverdueLoanBusiness
Player failed to repay a business loan on time
EmployeeLoanIndividual
Employee granted an individual loan
EmployeeRejectLoanIndividual
Employee rejected an individual loan
EmployeeClockOut
Employee clocked out (ended duty)
EmployeeClockIn
Employee clocked in (started duty)
BossFireEmployee
Boss fired an employee
BossChangeJobGrade
Boss changed an employee's job grade
BossHireEmployee
Boss hired a new employee
CompanyBankDeposit
Deposit made into the company bank account
CompanyBankWithdrawal
Withdrawal made from the company bank account
Last updated