# 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 %}


---

# 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://codeforge.gitbook.io/codeforge/sleek-series/sleek-banking.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.
