> For the complete documentation index, see [llms.txt](https://codeforge.gitbook.io/codeforge/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://codeforge.gitbook.io/codeforge/sleek-series/sleek-banking.md).

# SLEEK BANKING

{% embed url="<https://youtu.be/HYGX-gWBcnM?si=OhWtznZFg3SCPX4H>" %}

### Work Guide

This is a quick, player‑facing flow you can copy into your community docs.

#### Bank & ATM access

* **Open a bank** at any bank NPC/location (blips are provided).\
  If target is disabled, press the configured key (default **E**, control code `38`) near the banker.
* **Open an ATM** at any ATM prop or listed ATM position (auto‑detection can be enabled).

#### Credit card & PIN

* Buy a **credit card** from the bank UI (if enabled in config).
* If the server requires a card **item**, the player must **use** that item to open ATM banking.
* Set a **PIN** (length defined in config). PIN is requested when opening via ATM (if enabled).

#### Accounts & IBAN

* Each account has an **IBAN** (auto‑generated). Optionally allow players to **change** their IBAN for a fee.
* View **balance**, **last transactions**, **totals deposited/withdrawn**.

#### Cash deposit / withdrawal / transfer

* **Deposit** cash to bank balance&#x20;
* **Withdraw** cash from bank
* **Transfer** to any other valid IBAN; transfers work to **online or offline** targets.

#### Loans

* Request a **loan** with server‑side validated amount & installments.
* Interest is calculated dynamically based on installments; **late penalties** can apply.
* Repayments are scheduled automatically;

#### Savings

* Open a **savings account** (one‑time activation cost).
* **Deposit** / **withdraw** (withdrawals can have a fee).
* **Interest** is accrued automatically at the configured interval; shows **next interest time**.

#### History & limits

* UI shows **recent transactions** and a paginated **transactions tab** (limits are configurable).

***

### Installation

1. **Download & place the resource**
   * Put the entire folder **`sleek-bank`** into your server’s `resources` directory.
   * **Do not rename** the folder.
2. **Start order in `server.cfg`**

   ```lua
   # Framework & deps first
   ensure es_extended      # or qb-core / qbox
   ensure oxmysql          # or your SQL plugin
   ensure ox_target        # or qb-target (optional)
   ensure ox_inventory     # or qb-inventory / qs-inventory (optional)

   # Then Sleek Bank
   ensure sleek-bank
   ```
3. **Database**
   * Import `sleek-bank/sleek-bank.sql` into your DB.\
     It creates:
     * `sleekbank_accounts`
     * `sleekbank_loans`
     * `sleekbank_savings`
     * `sleekbank_transactions` (with useful indexes)
4. **Inventory item (optional but recommended)**
   * If `Config.CreditCardRequiresItem = true`, add the **`credit_card`** item to your inventory system (see [Inventory Items](#inventory-items-credit-card)).
5. **Clear cache & restart**
   * Clear server and client cache (FiveM).
   * Restart the server.

***

### Configuration

All options are in **`config.lua`**. Below is a guided overview (names exactly match the file).

#### Core & Framework

```lua
Config.Debug            = false     -- Extra logs
Config.CurrencySymbol   = "$"

Config.Framework        = "ESX"     -- "ESX", "QB", "QBOX"
Config.SQL              = "OXMYSQL" -- "OXMYSQL", "MYSQL-ASYNC", "GHMATTIMYSQL"

-- Target system or floating text
Config.Target           = "ox_target"  -- "ox_target", "qb-target" or "" (empty = floating 3D text)
Config.OpenKey          = 38           -- Only used if Target = ""
```

#### Banks, ATMs & Targeting

* **Bank positions** (3D text or target zone):

  ```lua
  Config.BankPositions = {
    vector3(150.266, -1040.203, 29.374),
    -- ... more in config.lua
  }
  ```
* **ATMs**
  * **Automatic detection** of props can be enabled:

    ```lua
    Config.ATMDetection = {
      useAutomaticDetection = true,
      maxDetectionRange = 400.0,
      updateInterval   = 5000
    }
    ```
  * **Static ATM positions** (always checked):

    ```lua
    Config.ATMPositions = {
      vector3(145.91, -1035.44, 29.27),
      -- ... many more in config.lua
    }
    ```
  * **ATM prop models** (used for auto‑detection), e.g.:

    ```lua
    Config.ATMModels = {
      `prop_atm_01`, `prop_atm_02`, `prop_atm_03`,
      `prop_fleeca_atm`, `v_5_b_atm1`, `v_5_b_atm2`,
      `ch_prop_ch_atm_01a`, `ch_prop_ch_atm_02a`,
      `prop_atm_01_old`, `prop_atm_02_old`, `prop_atm_03_old`
    }
    ```
* **Blips & Bank NPCs**\
  Blips and banker peds are configured under `Config.Blips` and `Config.BankNPCs` with sprite, color, and idle animations.

> **Server‑side safety:** open requests validate proximity to bank/ATM; ATM range is \~3.0 units.

#### Fees & IBAN

* **Transaction fees** (percentages; 0.02 = 2%):

  ```lua
  Config.TransactionFees = {
    deposit  = 0.0,
    withdraw = 0.01,
    transfer = 0.02
  }
  ```
* **IBAN**

  ```lua
  Config.IBAN = {
    Prefix           = "BANK",              -- e.g. "BANK" → "BANKA3X8F2"
    MaxLength        = 16,                  -- total, including prefix
    GenerationMethod = "random_alphanumeric", -- "random_numeric" | "random_alphanumeric"
    AllowUserChange  = true,
    ChangeCost       = 5000
  }

  Config.MaxLastTransactions    = 4   -- shown on Home
  Config.MaxAllTransactionsLoad = 50  -- initial list size on Transactions tab
  ```

#### Credit Card & PIN

```lua
Config.EnableCreditCard       = true
Config.CreditCardCost         = 1100
Config.CreditCardRequiresItem = true        -- requires item to use ATM flows
Config.CreditCardItemName     = "credit_card"
Config.CreditCardUsesMetadata = true        -- attach IBAN metadata to the item

Config.EnablePinScreenForATM  = true        -- ask for PIN when opening via ATM
Config.PinLength              = 4           -- 4..16 supported
```

**How it works**

* If `CreditCardRequiresItem = true`, the usable item is registered server‑side:
  * ESX: `ESX.RegisterUsableItem`
  * QB/QBOX: `QBCore.Functions.CreateUseableItem`
  * ox\_inventory: an item callback is exported by name
* The server guards ATM access with a one‑time **secret token** only created inside the item callback, so only legit card uses can open ATM banking.
* If `CreditCardUsesMetadata = true`, the card item stores the **IBAN** of its owner.

#### ATM Animations

```lua
Config.EnableATMAnimation = true
Config.ATMAnimation = {
  dict = "amb@prop_human_atm@male@idle_a",
  name = "idle_a"
}
```

#### Loans

```lua
Config.Loan = {
  -- Request limits & defaults
  minAmount           = 600,
  maxAmount           = 10000,
  defaultAmount       = 1000,
  amountStep          = 100,

  minInstallments     = 3,
  maxInstallments     = 24,
  defaultInstallments = 6,

  -- Interest model
  baseInterestRate                = 0.03,  -- e.g. 3%
  interestIncrementPerInstallment = 0.002, -- +0.2% per installment above min

  -- Repayment schedule
  paymentIntervalHours   = 1,    -- hours; set to **"test"** for one‑minute intervals during QA

  -- Late penalty
  LatePaymentPenaltyPercent = 0.10 -- applied if the payment is late
}
```

**Server behavior**

* Total owed: `principal * (1 + interestRate)`, where\
  `interestRate = baseInterestRate + (installments - minInstallments) * interestIncrementPerInstallment`.
* Payments are scheduled and applied even if the recipient is **offline**.
* The **penalty** is added to the next installment when late.

#### Savings

```lua
Config.EnableSavingsSystem = true
Config.Savings = {
  activationCost        = 5000,     -- one‑time
  maximumBalance        = 1000000,

  -- Interest (auto‑applied by server thread)
  interestRate          = 0.05,     -- 5%
  interestIntervalHours = 6,

  -- Deposit defaults (UI sliders; server still validates)
  minDeposit            = 100,
  maxDeposit            = 10000,
  defaultDeposit        = 1000,

  -- Withdrawals
  withdrawalFeePercent  = 0.02      -- applied to all savings withdrawals
}
```

**Server behavior**

* Savings interest is queued and applied on schedule.
* Interest is skipped when the balance exceeds `maximumBalance`.
* UI shows **next interest timestamp**.

#### Localization

* `Config.Locale = 'en'` (built‑in: `en, es, fr, it, de, pt, tr, ar, zh`).
* UI strings are available both in **Lua** and UI **JS** (`html/js/translation.js`).
* You can translate the front‑end HTML/JS freely; the UI is responsive.

***

### Inventory Items (credit card)

If `Config.CreditCardRequiresItem = true`, add **`credit_card`**:

* **ox\_inventory – items.json** (example)

  ```json
  {
    "credit_card": {
      "label": "Credit Card",
      "weight": 0,
      "stack": false,
      "close": true,
      "description": "Access your bank account at ATMs."
    }
  }
  ```

  If `Config.CreditCardUsesMetadata = true`, the server will attach `{ iban = "<PLAYER_IBAN>" }` as item metadata on purchase.
* **qb-inventory – shared/items.lua** (example)

  ```lua
  ["credit_card"] = {
      ["name"] = "credit_card",
      ["label"] = "Credit Card",
      ["weight"] = 0,
      ["type"] = "item",
      ["image"] = "credit_card.png",
      ["unique"] = true,
      ["useable"] = true,
      ["shouldClose"] = true,
      ["combinable"] = nil,
      ["description"] = "Access your bank account at ATMs."
  },
  ```

> The resource registers the **usable item** automatically (ESX / QB / QBOX / ox\_inventory / qs-inventory). No extra code needed.

***

### Troubleshooting & Tips

* **Nothing happens at ATM**
  * If `CreditCardRequiresItem = true`, players must **use the card item** (not just press E).
  * Ensure `Config.EnablePinScreenForATM` and a valid PIN if you enforce PIN.
  * Check you’re near a configured **ATM position** or that **auto‑detection** is enabled with correct `Config.ATMModels`.
* **IBAN change fails**
  * IBAN must **start with `Config.IBAN.Prefix`** and have **exactly `Config.IBAN.MaxLength`** characters.
  * Only alphanumeric characters allowed (depends on `GenerationMethod`).
* **Transfers to offline players**
  * Supported. The transaction is posted and balances update in DB.\
    Post‑amount snapshots are recorded for both sides.
* **Loan “test mode”**
  * Set `Config.Loan.paymentIntervalHours = "test"` to make intervals **1 minute** for QA.
* **Performance**
  * Auto‑detection scans ATM props near players at `updateInterval`. Adjust `maxDetectionRange` and interval if needed.
* **Localization**
  * `Config.Locale` selects server messages; UI translations are in `html/js/translation.js` and can be edited freely.

***

{% hint style="success" %}
**If you want to edit the aesthetics or design. You have the HTML open so you can modify the style and everything as you want.**

The script is **RESPONSIVE** for all resolutions as well.
{% endhint %}
