> ## Documentation Index
> Fetch the complete documentation index at: https://docs.shdevelopment.org/llms.txt
> Use this file to discover all available pages before exploring further.

# sh-courthouse: Courthouse & Justice System for RedM

> sh-courthouse adds courthouse case management, fine payments, fine disputes, warrant review, jail appeals, small claims, hearings, summons, and case docket workflows for RedM servers using sh-policemdt.

`sh-courthouse` is a courthouse companion resource for `sh-policemdt`. It adds a dedicated courthouse NUI and Fine Desk NPC for legal roleplay workflows: warrant review, citizen fine payments, fine disputes, jail appeals, small claims, court hearings, summons delivery, case participants, docket entries, and judicial rulings.

The resource supports VORP and RSG framework identity/job detection, stores courthouse case data in MySQL, and uses `sh-policemdt` as the source of truth for MDT people, fines, jail records, and approved warrants.

## Requirements

* RedM server using `fx_version 'cerulean'`
* `oxmysql`
* `sh-policemdt` installed and started
* VORP (`vorp_core`) or RSG (`rsg-core` / `rsg-core-main`)
* Optional: `sh-telegram` for in-character court notices, summons, and receipts

<Note>
  `sh-policemdt` is a hard dependency. `sh-courthouse` reads MDT people/fines/jail records and calls MDT bridge exports for fine payments, fine changes, jail sentence changes, and approved warrant creation.
</Note>

## Installation

<Steps>
  <Step title="Install the resource">
    Place the folder in your server resources directory and keep the folder name as `sh-courthouse`.
  </Step>

  <Step title="Check dependencies">
    Make sure `oxmysql`, your framework, and `sh-policemdt` are installed. Enable `sh-telegram` only if you want courthouse notices delivered through telegrams.
  </Step>

  <Step title="Add ensure order">
    Start the framework, `oxmysql`, `sh-policemdt`, optional `sh-telegram`, then `sh-courthouse`.

    ```cfg server.cfg theme={null}
    ensure oxmysql
    ensure vorp_core      # or rsg-core / rsg-core-main
    ensure sh-policemdt
    ensure sh-telegram    # optional
    ensure sh-courthouse
    ```
  </Step>

  <Step title="Configure framework and roles">
    Edit `config.lua`, then map your server job names or job types to courthouse roles in `Config.Access`.
  </Step>

  <Step title="Configure Fine Desk">
    Set the Fine Desk NPC locations and make sure `sh-policemdt` is not also spawning a duplicate fine payment NPC.
  </Step>

  <Step title="Start and test">
    Start the resource, open `/courthouse` on a judge character, review the counters, and test a fine payment through the Fine Desk NPC.
  </Step>
</Steps>

<Tip>
  You do not need to import a separate courthouse SQL file. On resource start, `sh-courthouse` creates its courthouse tables automatically with `CREATE TABLE IF NOT EXISTS`. The MDT tables still come from `sh-policemdt`.
</Tip>

## Framework Support

Set the framework in `config.lua`:

```lua config.lua theme={null}
Config.Framework = 'auto' -- auto | vorp | rsg
```

`auto` checks for `vorp_core`, `rsg-core`, or `rsg-core-main`. You can force `vorp` or `rsg` if your server runs both or if auto detection chooses the wrong framework.

## Core Config

```lua config.lua theme={null}
Config.Locale = 'en' -- en, es, de
Config.Debug = true
Config.ServerYear = 1899

Config.SHTelegram = true
Config.SHHousing = false   -- future implementation
Config.SHLicenses = false  -- future implementation
```

`Config.ServerYear` is used when building court case numbers. For example, case prefixes include `CRT`, `WRT`, `JAT`, `FDT`, `SCL`, `CVL`, `BSD`, `PRP`, and `HRG`.

<Note>
  `Config.SHHousing` and `Config.SHLicenses` are present for future integrations. They do not currently add property dispute or license suspension behavior by themselves.
</Note>

## Opening the Courthouse

The courthouse NUI opens with `/courthouse` by default:

```lua config.lua theme={null}
Config.NUI = {
    OpenCommand = 'courthouse',
    RequestTimeoutMs = 8000,
}
```

Staff users get the courthouse ledger interface. Citizens can use `/courthouse` only when citizen actions are enabled. The Fine Desk NPC is separate and can still be used for fine payment when the courthouse Fine Desk is enabled.

## Role-Based Access

`sh-courthouse` uses role flags instead of one grade threshold. Map your framework job names to one or more courthouse roles:

```lua config.lua theme={null}
Config.Access = {
    AllowCitizenActions = true,

    Vorp = {
        judge      = { judge = true, marshal = true },
        clerk      = { courtclerk = true },
        lawyer     = { lawyer = true, marshal = true },
        prosecutor = { prosecutor = true },
        defender   = { defender = true },
        bailiff    = { marshal = true },
    },

    Rsg = {
        judge      = { judge = true, marshal = true },
        clerk      = { courtclerk = true },
        lawyer     = { lawyer = true, marshal = true },
        prosecutor = { prosecutor = true },
        defender   = { defender = true },
        bailiff    = { bailiff = true },
    },
}
```

| Role           | Access                                                                                                                                                        |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Judge**      | Decide warrants, fine disputes, jail appeals, and small claims. Record trial rulings. Schedule and update hearings. Issue summons.                            |
| **Clerk**      | Schedule and update hearings, issue summons, review calendars, manage case phases and participants, and maintain case files. Cannot issue judicial decisions. |
| **Lawyer**     | File and track fine disputes, jail appeals, and small claims. Add case docket entries. Cannot issue judicial decisions.                                       |
| **Prosecutor** | Same legal counsel workflow as lawyer for prosecution-side case work.                                                                                         |
| **Defender**   | Same legal counsel workflow as lawyer for defense-side case work.                                                                                             |
| **Bailiff**    | Read-only courthouse staff access for calendar and case detail views.                                                                                         |
| **Citizen**    | If `AllowCitizenActions = true`, can view/file their own eligible disputes, appeals, and small claims through `/courthouse`.                                  |

<Warning>
  Job names are normalized to lowercase. Make sure your configured job names match the framework job names exactly after lowercasing.
</Warning>

## Main Workflows

<Accordion title="Warrant Review">
  `sh-policemdt` submits warrant requests through the `SubmitWarrantRequestFromMDT` export. Courthouse staff can view pending requests, but only judges can approve or deny them. Approved requests call back into `sh-policemdt` to create the actual MDT warrant.
</Accordion>

<Accordion title="Fine Desk Payments">
  The Fine Desk tab and NPC load unpaid fines from `sh-policemdt`. Citizens can pay one fine or pay all outstanding fines. Payment receipts can be sent through `sh-telegram` and logged to the `FinePayments` webhook.
</Accordion>

<Accordion title="Fine Disputes">
  Citizens and legal counsel can dispute a fine. Judges decide disputes as `upheld`, `reduced`, or `dismissed`. Reduced and dismissed outcomes call MDT bridge exports to update or void the MDT fine.
</Accordion>

<Accordion title="Small Claims">
  Citizens, judges, clerks, and legal counsel can file small claims against an MDT person profile. Judges can deny a claim or approve it and immediately schedule a hearing.
</Accordion>

<Accordion title="Jail Appeals">
  Citizens and legal counsel can file appeals against jail records from `sh_mdt_jail_records`. Judges can approve or deny appeals. Approved appeals adjust the active jail sentence through the MDT bridge.
</Accordion>

<Accordion title="Court Calendar & Summons">
  Judges and clerks can schedule hearings, update hearing status, and issue summons. Summons can target all involved parties, plaintiff, defendant, a participant role, or a specific involved person ID.
</Accordion>

<Accordion title="Case Detail & Trials">
  Staff can open case details, view participants, notes, hearings, and timeline entries. Judges and clerks manage case phases and participants. Judges record rulings. Judges, clerks, lawyers, prosecutors, and defenders can add docket entries.
</Accordion>

## Fine Desk NPC

Configure the Fine Desk NPC in `config.lua`:

```lua config.lua theme={null}
Config.PayFineNPC = {
    Enabled = true,

    PedModel = 's_m_m_bankclerk_01',
    Scenario = 'WORLD_HUMAN_STAND_WAITING',

    Locations = {
        vector4(-805.24, -1199.42, 44.19, 272.13),
    },

    InteractionDistance = 2.2,
    PromptControl = 0xE30CD707,
    PromptLabel = 'Visit Courthouse',
    PromptGroupLabel = 'Courthouse Desk',

    ShowBlip = true,
    Blip = {
        Style = 1664425300,
        Sprite = 2107754879,
        Name = 'Courthouse Desk',
        Scale = 0.2,
        Color = nil,
    },
}
```

The NPC only becomes available when `Config.PayFineNPC.Enabled = true` and the MDT bridge reports that courthouse fine desk handling is enabled.

<Warning>
  If `sh-policemdt` also has a fine payment NPC enabled, disable the MDT NPC to avoid duplicate fine desk prompts. The comment in this resource references `Config.PayFinesNPC` / `Config.PayFineNPC` depending on the MDT version, so check your `sh-policemdt` config for the exact key.
</Warning>

## sh-telegram Integration

Enable telegram delivery in `config.lua`:

```lua config.lua theme={null}
Config.SHTelegram = true
```

When enabled and `sh-telegram` is running, courthouse notices can be delivered as telegram notifications and persisted inbox messages. This is used for summons, fine receipts, warrant updates, dispute rulings, appeal rulings, small claim notices, and hearing updates.

If `sh-telegram` is disabled or unavailable, the resource falls back to courthouse notifications where supported.

## Discord Webhooks

Enable Discord webhook logging per event type:

```lua config.lua theme={null}
Config.Webhooks = {
    Enabled = false,
    Name = 'sh-courthouse',
    FinePayments = '',
    FineDisputes = '',
    Warrants = '',
    JailAppeals = '',
    Hearings = '',
    Trials = '',
}
```

| Webhook        | Events                                                                                           |
| -------------- | ------------------------------------------------------------------------------------------------ |
| `FinePayments` | Fine payment receipts                                                                            |
| `FineDisputes` | Fine dispute filings and judicial decisions                                                      |
| `Warrants`     | Warrant request decisions                                                                        |
| `JailAppeals`  | Jail appeal filings and rulings                                                                  |
| `Hearings`     | Hearing scheduling, hearing updates, summons, and small claim decisions                          |
| `Trials`       | Small claim filings, case notes, docket entries, participant changes, phase updates, and rulings |

## Database Tables

On resource start, `sh-courthouse` creates these courthouse tables if they do not exist:

| Table                        | Purpose                                                                                |
| ---------------------------- | -------------------------------------------------------------------------------------- |
| `sh_court_cases`             | Main case records, case numbers, status, assigned judge, and ruling summary            |
| `sh_court_case_notes`        | Case notes, timeline entries, docket entries, decisions, and status changes            |
| `sh_court_case_participants` | Plaintiff, defendant, judge, counsel, witnesses, bailiff, jury, and other participants |
| `sh_court_warrant_requests`  | Pending and decided warrant review requests                                            |
| `sh_court_fine_disputes`     | Fine dispute filings and outcomes                                                      |
| `sh_court_jail_appeals`      | Jail appeal filings and outcomes                                                       |
| `sh_court_small_claims`      | Small claim filings, decisions, and linked hearings                                    |
| `sh_court_hearings`          | Hearing schedule, status, agenda, courtroom, and summons timestamp                     |

The resource also reads from `sh-policemdt` tables such as `sh_mdt_people`, `sh_mdt_fines`, and `sh_mdt_jail_records`.

## Integration Notes

`sh-courthouse` expects these bridge exports from `sh-policemdt`:

| Export                             | Purpose                                                     |
| ---------------------------------- | ----------------------------------------------------------- |
| `GetOutstandingFinesForSource`     | Loads the current player's unpaid fines                     |
| `PayOutstandingFinesForSource`     | Pays all unpaid fines for the current player                |
| `PayFineByIdForSource`             | Pays one selected fine                                      |
| `VoidFineForCourt`                 | Voids a fine after a dismissed dispute                      |
| `ReduceFineForCourt`               | Reduces a fine after a reduced dispute ruling               |
| `CreateApprovedWarrantForCourt`    | Creates an MDT warrant after judge approval                 |
| `AdjustActiveJailSentenceForCourt` | Applies approved jail appeal sentence changes               |
| `GetCourthouseFineDeskState`       | Tells the courthouse whether the Fine Desk should be active |

If the courthouse UI opens but actions fail with bridge errors, restart `sh-policemdt` first, then restart `sh-courthouse`.

## Troubleshooting

<Accordion title="The resource stops after starting">
  Confirm the folder is named exactly `sh-courthouse`.
</Accordion>

<Accordion title="/courthouse says a staff role is required">
  Check `Config.Access` for the active framework. Job names are matched against the player's framework job name, and RSG can also use job type allowlists when configured.
</Accordion>

<Accordion title="Fine Desk NPC does not appear">
  Confirm `Config.PayFineNPC.Enabled = true`, `sh-policemdt` is started, and MDT courthouse fine desk handling is enabled. The client polls the server every 15 seconds for Fine Desk availability.
</Accordion>

<Accordion title="Fine payments, fine disputes, warrants, or appeals fail">
  Confirm `sh-policemdt` is running and includes the courthouse bridge exports expected by this resource.
</Accordion>

<Accordion title="Summons do not reach players">
  Confirm involved parties are attached to the case with MDT person IDs. For telegram delivery, confirm `Config.SHTelegram = true`, `sh-telegram` is started, and users have telegram records.
</Accordion>
