# Crowe Society

> **A comprehensive society management system for RedM servers featuring dynamic society creation, member management, rank systems, financial tracking, duty system, salary management, and modern announcements/bulletin board.**

***

## Table of Contents

* [Overview](#overview)
* [Features](#features)
* [Installation](#installation)
* [Configuration](#configuration)
* [Commands](#commands)
* [Usage Guide](#usage-guide)
* [API Reference](#api-reference)
* [Integration Examples](#integration-examples)
* [Troubleshooting](#troubleshooting)
* [Support](#support)

***

## Overview

The Crowe Society Management System is a complete organization management solution for RedM servers built on the VORP framework. It provides everything needed to create, manage, and operate societies with advanced features like duty systems, salary management, and real-time notifications.

### Key Highlights

* 🏢 **Dynamic Society Creation** - Create societies anywhere in the world
* 👥 **Advanced Member Management** - Character-specific memberships with comprehensive tracking
* 📊 **Flexible Rank System** - 5-tier customizable rank structures
* 💰 **Financial Management** - Complete funds tracking with transaction history
* ⏰ **Duty & Salary System** - Clock in/out functionality with automatic salary processing
* 📢 **Announcements Board** - Organization-wide communication system
* 🎨 **Customizable UI** - Theme presets and custom color options
* 🌍 **Multi-Language Support** - 14 languages out of the box
* 🔔 **Advanced Notifications** - Integration with Crowe notification systems

***

## Features

### 🏢 Dynamic Society Creation

Create societies anywhere in the world using commands or UI with:

* **10+ Society Types**: Business, Law Enforcement, Medical, Mining, Rancher, Stable, and more
* **Free Creation**: Zero starting funds and creation costs
* **Unique Locations**: Each society gets interactive blip and NPC
* **Configurable Limits**: Set maximum societies per server
* **Distance Validation**: Prevent overlapping society locations

### 👥 Member Management System

Comprehensive member roster management featuring:

* **Character-Specific Membership**: Each character has separate society memberships (Steam ID + Character ID)
* **Member Actions**: Invite, kick, and promote members with proper permissions
* **Status Tracking**: Active, inactive, kicked, and left status tracking
* **Duty System**: Clock in/out functionality with real-time status tracking
* **VORP Integration**: Seamless player identifier integration

### 📊 Advanced Rank System

Flexible rank structures with:

* **5-Tier Default System**: Recruit → Member → Officer → Lieutenant → Leader
* **Society-Specific Ranks**: Unique rank structures per society type
* **Granular Permissions**: 10 different permission levels
* **JSON-Based Storage**: Flexible permission system for easy customization

### 💰 Financial Management

Complete financial tracking system including:

* **Funds Management**: Society funds tracking with real-time updates
* **Transaction History**: Multiple transaction types with detailed logging
* **External API**: `AddMoneyToSociety()` for integration with other scripts
* **Audit Trails**: Complete financial history for reporting
* **Balance Calculations**: Automatic balance updates and validation

### ⏰ Duty & Salary System

Advanced duty and compensation management:

* **Duty Management**: Location-based clock in/out system
* **Salary Configurations**: Custom time intervals (minutes, hours, days, weeks, months, years)
* **Automatic Payouts**: Time-based salary processing with optimization
* **On-Demand Payments**: Manual salary payments for commission work
* **Duty Integration**: Only pay salaries to members who are ON DUTY
* **Real-time Status**: Live duty status indicators in UI

### 📢 Announcements / Bulletin Board

Organization-wide communication system:

* **Post Announcements**: Title, body, optional expiry, and links
* **Management Features**: Pin/unpin and delete announcements (rank ≥ 4)
* **Modal Views**: Compact list with detailed "read more" view
* **Localization**: Fully localized UI and client-side rendering

### 🎨 Customizable Theme UI

Modern, responsive interface with:

* **Theme Presets**: Switch between different visual themes
* **Custom Colors**: Fine-tune colors in the in-UI Settings
* **Smooth Animations**: Professional transitions and effects
* **Responsive Design**: Works on all screen sizes
* **Duty Indicators**: Visual duty status with colored badges
* **Real-time Updates**: Live data refresh without page reloads

### 🌍 Multi-Language Support

Comprehensive localization featuring:

* **14 Languages**: en, es, fr, de, it, ja, ko, nl, pl, pt, ru, tr, zh, ar
* **Extensible System**: Easy to add new languages via locale files
* **Complete Coverage**: All UI elements translated
* **Client-Side Rendering**: Fast, responsive translations

### 🔔 Advanced Notification System

Integrated notification system with:

* **Crowe Notification**: Seamless integration with advanced notification system
* **Crowe Libs**: Essential utility functions for money operations and spawn detection
* **Fallback Support**: Built-in NUI notifications when external systems unavailable
* **Real-time Alerts**: Instant notifications for invites, salary payments, and duty changes

#### 🔗 V2 Features

* **Discord Webhooks**: Log society events (create, disband, invite, kick, deposit, withdraw, rank change, duty) to a configurable Discord channel. Toggle per event in `Config.Webhooks.events`.
* **Blip Customization**: Leaders customize society blips from Settings—sprite, color, display name, on/off. Creation form includes blip sprite and color dropdowns. Stored in DB.
* **VORP Job Sync (MultiJob)**: Optionally link a society to a VORP job. Join/leave/rank change syncs with VORP multiJob; clock-in sets active job; in-UI job switcher and remove-job with DB persistence. Config: `Config.VORPJobSync`.
* **Government Entity**: At creation, option "Government entity (infinite funds)". Government societies: balance shows "Government funded", deposits are disabled, withdrawals and salaries are not deducted from the ledger.

***

## Installation

### Prerequisites

#### Required Dependencies

* **vorp\_core** - Core framework for player management
* **vorp\_character** - Character system integration
* **oxmysql** - Database operations
* **crowe\_libs** - **REQUIRED** for money operations, spawn detection, and utility functions

#### Optional Dependencies

* **crowe\_notification** - Advanced notification system with enhanced UI

### Installation Steps

1. **Install Dependencies**

   ```bash
   # Ensure you have vorp_core, vorp_character, oxmysql, and crowe_libs installed
   # The script will fail to start without crowe_libs
   ```
2. **Add Resource**

   ```bash
   # Place crowe_society folder in your resources directory
   resources/[rp]/crowe_society/
   ```
3. **Start Resource**

   ```lua
   -- Add to server.cfg (after dependencies)
   ensure crowe_society
   ```
4. **Import Database**

   ```sql
   -- Run crowe_society.sql in your database
   source crowe_society.sql
   ```
5. **Configure Settings**

   ```lua
   -- Edit config.lua to your preferences
   -- See Configuration section for details
   ```
6. **Restart Server**

   ```bash
   # Restart your server to load the new resource
   ```

> **⚠️ Important**: The script will **fail to start** without `crowe_libs` as it's required for money operations and core functionality.

***

## Configuration

All configuration is handled in `config.lua`. Here are the key settings:

### Society Configuration

```lua
Config.Society = {
    maxSocieties = 10,                    -- Maximum societies on server
    maxMembersPerSociety = 50,            -- Maximum members per society
    creationCost = 0.00,                  -- Free society creation
    defaultFunds = 0.00,                  -- Zero starting funds
    allowCommandCreation = true,          -- Allow creation via commands
    minDistanceBetweenSocieties = 100.0   -- Minimum distance between societies
}
```

### Salary Configuration

```lua
Config.Salary = {
    maxSalariesPerSociety = 10,           -- Maximum salary configurations
    minSalaryAmount = 0.01,               -- Minimum salary amount
    maxSalaryAmount = 10000.00,           -- Maximum salary amount
    automaticProcessing = true,           -- Enable automatic salary processing
    dutyRequirement = true,               -- Require duty for salary payments
    defaultCheckInterval = 60000,         -- Default check interval (1 minute)
    optimization = {
        enableDynamicReoptimization = true,     -- Dynamic interval adjustment
        reoptimizationInterval = 300000,        -- Re-optimize every 5 minutes
        logOptimizationChanges = true           -- Log interval changes for debugging
    }
}
```

### Command Configuration

```lua
Config.Commands = {
    createSociety = "createsociety",      -- Command to create society
    disbandSociety = "disbandsociety",    -- Command to disband society
    manageSociety = "society",            -- Command to manage society (admin only)
    adminDisbandSociety = "admindisbandsociety", -- Admin disband command
    
    -- Permissions for society management command
    societyCommandPermissions = {
        "group.admin",
        "group.moderator"
    }
}
```

### Permission System

The system uses a granular permission structure with 10 different permission levels:

* `view_members` - View society member list
* `view_info` - View society information
* `contribute_funds` - Contribute money to society
* `invite_members` - Invite new members
* `kick_members` - Remove members from society
* `manage_activities` - Create and manage activities
* `manage_finances` - Handle society finances
* `manage_salaries` - Create and manage salary configurations
* `manage_ranks` - Modify rank structure
* `disband_society` - Dissolve the society
* `all` - All permissions (Leader rank)

***

## Commands

### Player Commands

| Command                               | Description                                   | Example                                                      |
| ------------------------------------- | --------------------------------------------- | ------------------------------------------------------------ |
| `/createsociety [name] [description]` | Create a new society at your current location | `/createsociety "Valentine Trading" "Local trading company"` |
| `/disbandsociety [name]`              | Disband your society (leaders only)           | `/disbandsociety "Valentine Trading"`                        |
| `/societyinvite`                      | Open invite management interface              | `/societyinvite`                                             |

### Admin Commands

| Command                            | Description                          | Example                  |
| ---------------------------------- | ------------------------------------ | ------------------------ |
| `/society`                         | Open society management interface    | `/society`               |
| `/admindisbandsociety [societyId]` | Force disband a society (admin only) | `/admindisbandsociety 5` |

### Interaction Keys

| Key                 | Action                  | Description                |
| ------------------- | ----------------------- | -------------------------- |
| **G Key** (default) | Open society management | When near society location |
| **F Key** (default) | Toggle duty status      | When near society location |

***

## Usage Guide

### Creating a Society

1. **Choose Location**
   * Stand at the desired location for your society
   * Ensure it meets minimum distance requirements from other societies
2. **Create Society**

   ```bash
   /createsociety "Society Name" "Description"
   ```
3. **Society Setup**
   * Your society will be created with a blip, NPC, and interactive area
   * You automatically become the Leader (rank 5)
   * Society starts with zero funds

### Managing Your Society

1. **Open Management Interface**
   * Use `/society` command or press **G** near society location
   * Access all management features from the main interface
2. **Member Management**
   * Invite new members using the invite system
   * Promote/demote members based on their performance
   * Remove members if necessary
3. **Financial Management**
   * Deposit/withdraw funds as needed
   * View transaction history
   * Set up salary configurations
4. **Duty System Setup**
   * Members can clock in/out at society location
   * Only on-duty members receive automatic salary payments
   * Real-time duty status tracking

### Duty System

1. **Clock In**
   * Visit your society location
   * Press **F** key or click "✅ Clock In"
   * You'll receive confirmation notification
2. **On Duty Benefits**
   * Receive automatic salary payments
   * Access to duty-specific features
   * Real-time status indicators
3. **Clock Out**
   * Press **F** key or click "❌ Clock Out"
   * Stop receiving automatic payments
   * Update status for other members

### Salary Management

1. **Create Salary Configuration**
   * Set salary name, amount, and payment interval
   * Choose from: minutes, hours, days, weeks, months, years, or on-demand
2. **Assign Salaries**
   * Assign salary configurations to specific members
   * Only on-duty members receive automatic payments
3. **Process Payments**
   * Automatic processing based on configured intervals
   * Manual on-demand payments available
   * Complete transaction logging

***

## API Reference

The Crowe Society Management System provides **22 export functions** for integration with other scripts.

### Important: Society Name vs Display Name

All export functions use the society's **internal `name`** (identifier), not the display `name_title`:

* **`name`**: Internal identifier (e.g., `"valentine_trading_company"`) - used in exports
* **`name_title`**: Display name (e.g., `"Valentine Trading Company"`) - shown in UI

When using exports, always use the internal `name` field. You can find this in the database or by checking the society data structure.

### System Readiness

#### `OnReady(callback)`

Safely wait for the system to be fully initialized.

```lua
exports['crowe_society']:OnReady(function()
    print("Crowe Society is ready!")
    -- Safe to use all exports now
end)
```

#### `IsSocietyReady()`

Check if the system is fully initialized.

```lua
if exports['crowe_society']:IsSocietyReady() then
    -- System is ready
end
```

#### `IsPlayerReady(source)`

Check if a player is fully loaded and ready.

```lua
if exports['crowe_society']:IsPlayerReady(source) then
    -- Player is ready for society operations
end
```

### Duty System

#### `IsOnDuty(source, societyName)`

Check if a player is currently on duty.

```lua
local isOnDuty = exports['crowe_society']:IsOnDuty(source, "valentine_trading_company")
```

> **Note**: Use the society's internal `name` (identifier), not the display `name_title`. The internal name is typically lowercase with underscores.

#### `GetDutyStatus(source)`

Get duty status for all societies a player belongs to.

```lua
local dutyStatus = exports['crowe_society']:GetDutyStatus(source)
```

### Member Management

#### `GetPlayerRank(source, societyName)`

Get detailed rank information for a player.

```lua
local rank = exports['crowe_society']:GetPlayerRank(source, "valentine_trading_company")
-- Returns: { level = 3, name = "Sergeant", permissions = {...} }
```

#### `HasPermission(source, societyName, permission)`

Check if a player has a specific permission.

```lua
local canWithdraw = exports['crowe_society']:HasPermission(source, "valentine_trading_company", "withdraw_funds")
```

#### `IsMember(source, societyName)`

Check if a player is a member of a society.

```lua
local isMember = exports['crowe_society']:IsMember(source, "valentine_trading_company")
```

#### `IsLeader(source, societyName)`

Check if a player is the leader of a society.

```lua
local isLeader = exports['crowe_society']:IsLeader(source, "valentine_trading_company")
```

### Society Information

#### `GetPlayerSocieties(source)`

Get all societies a player belongs to.

```lua
local societies = exports['crowe_society']:GetPlayerSocieties(source)
```

#### `GetSocietyInfo(societyName)`

Get detailed information about a society.

```lua
local society = exports['crowe_society']:GetSocietyInfo("valentine_trading_company")
```

#### `GetSocietyMembers(societyName)`

Get all members of a society.

```lua
local members = exports['crowe_society']:GetSocietyMembers("valentine_trading_company")
```

### Financial Management

#### `AddMoneyToSociety(societyName, amount, description, typeOverride)`

Add money to a society from external scripts.

```lua
local success = exports['crowe_society']:AddMoneyToSociety("valentine_trading_company", 100.00, "Newspaper sale")
```

#### `WithdrawMoneyFromSociety(source, societyName, amount, description, typeOverride)`

Withdraw money with permission validation.

```lua
local success = exports['crowe_society']:WithdrawMoneyFromSociety(source, "valentine_trading_company", 50.00, "ATM withdrawal")
```

### Job System Compatibility

#### `GetJob(source)`

Get player's primary job and grade.

```lua
local job, grade = exports['crowe_society']:GetJob(source)
```

#### `HasJob(source, societyName)`

Check if a player has a specific job.

```lua
local hasJob = exports['crowe_society']:HasJob(source, "valentine_trading_company")
```

#### `GetAllJobs(source)`

Get all jobs a player belongs to.

```lua
local jobs = exports['crowe_society']:GetAllJobs(source)
```

### Salary Management

#### `GetPlayerSalary(source, societyName)`

Get salary information for a player.

```lua
local salary = exports['crowe_society']:GetPlayerSalary(source, "valentine_trading_company")
```

### System Management

#### `forceClockOutAllPlayers()`

Force all players to clock out (typically used during server shutdown).

```lua
exports['crowe_society']:forceClockOutAllPlayers()
```

***

## Integration Examples

### Police Script Integration

```lua
-- Enhanced police script with real-time duty checking
RegisterCommand('arrest', function(source, args)
    -- Check if player is ready first
    if not exports['crowe_society']:IsPlayerReady(source) then
        TriggerClientEvent('notification', source, "System loading, please wait...")
        return
    end
    
    -- Check if on duty for law enforcement
    if exports['crowe_society']:IsOnDuty(source, "valentine_sheriffs_office") then
        local rank = exports['crowe_society']:GetPlayerRank(source, "valentine_sheriffs_office")
        if rank and rank.level >= 2 then -- Deputy or higher
            -- Allow arrest with enhanced validation
            TriggerClientEvent('police:arrest', source, args[1])
        else
            TriggerClientEvent('notification', source, "You must be at least Deputy rank to arrest")
        end
    else
        TriggerClientEvent('notification', source, "You must be on duty to arrest suspects")
    end
end)
```

### Medical Script Integration

```lua
-- Check if player can heal (must be on duty for medical practice)
RegisterCommand('heal', function(source, args)
    if exports['crowe_society']:IsOnDuty(source, "valentine_medical_practice") then
        local rank = exports['crowe_society']:GetPlayerRank(source, "valentine_medical_practice")
        if rank and rank.level >= 3 then -- Doctor or higher
            -- Allow healing
            TriggerClientEvent('medical:heal', source, args[1])
        else
            TriggerClientEvent('notification', source, "You must be at least Doctor rank to heal")
        end
    else
        TriggerClientEvent('notification', source, "You must be on duty to provide medical care")
    end
end)
```

### Shop Script Integration

```lua
-- Check if player can access employee discount
RegisterServerEvent('shop:requestDiscount')
AddEventHandler('shop:requestDiscount', function()
    local source = source
    
    -- Check if player is on duty for any business society
    local societies = exports['crowe_society']:GetPlayerSocieties(source)
    for _, society in ipairs(societies) do
        if society.type == "business" and exports['crowe_society']:IsOnDuty(source, society.name) then
            -- Apply employee discount
            TriggerClientEvent('shop:applyDiscount', source, 0.15) -- 15% discount
            return
        end
    end
    
    -- No discount available
    TriggerClientEvent('notification', source, "Employee discount only available when on duty")
end)
```

### External Revenue Integration

```lua
-- Newspaper/Shop revenue integration
RegisterServerEvent('newspaper:sellPaper')
AddEventHandler('newspaper:sellPaper', function(paperType, amount)
    local source = source
    local societyName = "saint_denis_news" -- Society that owns this newspaper
    local revenue = amount * 5.00 -- $5 per paper
    
    -- Add revenue to society
    local success = exports['crowe_society']:AddMoneyToSociety(
        societyName, 
        revenue, 
        string.format("Newspaper sales - %d papers sold", amount)
    )
    
    if success then
        TriggerClientEvent('notification', source, 
            string.format("Added $%.2f to %s funds", revenue, societyName), 
            "success"
        )
    else
        TriggerClientEvent('notification', source, "Failed to add revenue to society", "error")
    end
end)
```

### System Readiness Integration

```lua
-- Safe initialization for external scripts
exports['crowe_society']:OnReady(function()
    print("^2[MY SCRIPT]^7 Crowe Society is ready - initializing job system")
    
    -- Now safe to use all society functions
    RegisterCommand('checkjob', function(source, args)
        local job, grade = exports['crowe_society']:GetJob(source)
        if job then
            TriggerClientEvent('notification', source, "Your job: " .. job .. " (Grade " .. grade .. ")")
        else
            TriggerClientEvent('notification', source, "You don't have a job")
        end
    end)
    
    print("^2[MY SCRIPT]^7 Job system initialized successfully")
end)
```

***

## Troubleshooting

### Common Issues

#### Script Won't Start

* **Check Dependencies**: Ensure `crowe_libs` is installed and started
* **Database**: Verify `crowe_society.sql` was imported successfully
* **Config**: Check `config.lua` for syntax errors

#### Players Can't Create Societies

* **Permissions**: Verify command permissions in config
* **Distance**: Check minimum distance between societies
* **Limits**: Ensure maximum society limit not reached

#### Duty System Not Working

* **Location**: Ensure player is within interaction distance
* **Membership**: Verify player is a member of the society
* **Permissions**: Check if player has duty permissions

#### Salary Payments Not Processing

* **Duty Status**: Ensure members are on duty for automatic payments
* **Configuration**: Check salary configuration settings
* **Funds**: Verify society has sufficient funds

### Debug Information

Enable debug logging in config:

```lua
Config.Debug = true
```

Check console for error messages and debug information.

### Performance Issues

* **Salary Processing**: Adjust check intervals in config
* **Blip Refresh**: Monitor blip refresh frequency
* **Database Queries**: Check for slow queries in logs

***

## Support

### Getting Help

1. **Check Documentation**: Review this guide and API reference
2. **Configuration**: Verify your `config.lua` settings
3. **Logs**: Check server console for error messages
4. **Dependencies**: Ensure all required resources are installed

### Reporting Issues

When reporting issues, please include:

* Server console logs
* Configuration file (sanitized)
* Steps to reproduce the issue
* Expected vs actual behavior

### Best Practices

1. **Use OnReady for initialization** - Always wait for system readiness
2. **Check player readiness** before using exports
3. **Use pcall for error handling** to prevent crashes
4. **Test with multiple societies** - Ensure compatibility
5. **Monitor performance** - Watch for resource usage

***

## License

This project is licensed under the MIT License - see the LICENSE file for details.

***

**Crowe Society Management System v1.0.0** - Complete organization management with duty and salary systems.

*For additional support or questions, please refer to the main documentation or contact the development team.*


---

# 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://crowescripts.gitbook.io/documentation/about-our-scripts/redm-script-documentation/crowe-society.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.
