# `PhoenixKit.Modules.Referrals`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v1.7.165/lib/modules/referrals/referrals.ex#L1)

Referral code system for PhoenixKit - complete management in a single module.

This module provides both the Ecto schema definition and business logic for
managing referral codes. It includes code creation, validation, usage tracking,
and system configuration.

## Schema Fields

- `code`: The referral code string (unique, required)
- `description`: Human-readable description of the code
- `status`: Boolean indicating if the code is active
- `number_of_uses`: Current number of times the code has been used
- `max_uses`: Maximum number of times the code can be used
- `created_by`: User ID of the admin who created the code
- `beneficiary`: User ID who benefits when this code is used (optional)
- `date_created`: When the code was created
- `expiration_date`: When the code expires

## Core Functions

### Code Management
- `list_codes/0` - Get all referral codes
- `get_code!/1` - Get a referral code by ID (raises if not found)
- `get_code_by_string/1` - Get a referral code by its string value
- `create_code/1` - Create a new referral code
- `update_code/2` - Update an existing referral code
- `delete_code/1` - Delete a referral code
- `generate_random_code/0` - Generate a random code string

### Usage Tracking
- `use_code/2` - Record usage of a referral code by a user
- `get_usage_stats/1` - Get usage statistics for a code
- `list_usage_for_code/1` - Get all usage records for a code
- `user_used_code?/2` - Check if user has used a specific code

### System Settings
- `enabled?/0` - Check if referral codes system is enabled
- `required?/0` - Check if referral codes are required for registration
- `enable_system/0` - Enable the referral codes system
- `disable_system/0` - Disable the referral codes system
- `set_required/1` - Set whether referral codes are required

## Usage Examples

    # Check if system is enabled
    if PhoenixKit.Modules.Referrals.enabled?() do
      # System is active
    end

    # Create a new referral code
    {:ok, code} = PhoenixKit.Modules.Referrals.create_code(%{
      code: "WELCOME2024",
      description: "Welcome promotion",
      max_uses: 100,
      created_by_uuid: admin_user.uuid,
      expiration_date: ~U[2024-12-31 23:59:59.000000Z]
    })

    # Use a referral code during registration
    case PhoenixKit.Modules.Referrals.use_code("WELCOME2024", user_uuid) do
      {:ok, usage} -> # Code used successfully
      {:error, reason} -> # Handle error
    end

# `change_code`

Returns an `%Ecto.Changeset{}` for tracking referral code changes.

## Examples

    iex> PhoenixKit.Modules.Referrals.change_code(code)
    %Ecto.Changeset{data: %PhoenixKit.Modules.Referrals{}}

# `changeset`

Creates a changeset for referral code creation and updates.

Validates that code is unique and all required fields are present.
Automatically sets date_created on new records.

# `count_user_codes`

Counts the total number of referral codes created by a user.

## Examples

    iex> PhoenixKit.Modules.Referrals.count_user_codes(1)
    5

# `create_code`

Creates a referral code.

## Examples

    iex> PhoenixKit.Modules.Referrals.create_code(%{code: "TEST123", max_uses: 10})
    {:ok, %PhoenixKit.Modules.Referrals{}}

    iex> PhoenixKit.Modules.Referrals.create_code(%{code: ""})
    {:error, %Ecto.Changeset{}}

# `delete_code`

Deletes a referral code.

## Examples

    iex> PhoenixKit.Modules.Referrals.delete_code(code)
    {:ok, %PhoenixKit.Modules.Referrals{}}

    iex> PhoenixKit.Modules.Referrals.delete_code(code)
    {:error, %Ecto.Changeset{}}

# `disable_system`

Disables the referral codes system.

Sets the "referral_codes_enabled" setting to false.

## Examples

    iex> PhoenixKit.Modules.Referrals.disable_system()
    {:ok, %Setting{}}

# `enable_system`

Enables the referral codes system.

Sets the "referral_codes_enabled" setting to true.

## Examples

    iex> PhoenixKit.Modules.Referrals.enable_system()
    {:ok, %Setting{}}

# `enabled?`

Checks if the referral codes system is enabled.

Returns true if the "referral_codes_enabled" setting is true.

## Examples

    iex> PhoenixKit.Modules.Referrals.enabled?()
    false

# `expired?`

Checks if a referral code has expired.

## Examples

    iex> PhoenixKit.Modules.Referrals.expired?(code)
    false

# `generate_random_code`

Generates a random 5-character alphanumeric referral code.

Returns a string with uppercase letters and numbers, excluding
potentially confusing characters (0, O, I, 1).

## Examples

    iex> PhoenixKit.Modules.Referrals.generate_random_code()
    "A7B2K"

# `get_code`

Gets a single referral code by integer ID or UUID.

Accepts:
- Integer ID (e.g., `123`)
- UUID string (e.g., `"550e8400-e29b-41d4-a716-446655440000"`)
- Integer string (e.g., `"123"`)
- Any other input returns `nil`

Returns the referral code if found, `nil` otherwise.

## Examples

    iex> PhoenixKit.Modules.Referrals.get_code(123)
    %PhoenixKit.Modules.Referrals{}

    iex> PhoenixKit.Modules.Referrals.get_code("550e8400-e29b-41d4-a716-446655440000")
    %PhoenixKit.Modules.Referrals{}

    iex> PhoenixKit.Modules.Referrals.get_code("123")
    %PhoenixKit.Modules.Referrals{}

    iex> PhoenixKit.Modules.Referrals.get_code(456)
    nil

    iex> PhoenixKit.Modules.Referrals.get_code(:invalid)
    nil

# `get_code!`

Same as `get_code/1`, but raises `Ecto.NoResultsError` if the code does not exist.

## Examples

    iex> PhoenixKit.Modules.Referrals.get_code!("550e8400-e29b-41d4-a716-446655440000")
    %PhoenixKit.Modules.Referrals{}

    iex> PhoenixKit.Modules.Referrals.get_code!("00000000-0000-0000-0000-000000000000")
    ** (Ecto.NoResultsError)

# `get_code_by_string`

Gets a single referral code by its string value.

Returns the referral code if found, nil otherwise.

## Examples

    iex> PhoenixKit.Modules.Referrals.get_code_by_string("WELCOME2024")
    %PhoenixKit.Modules.Referrals{}

    iex> PhoenixKit.Modules.Referrals.get_code_by_string("INVALID")
    nil

# `get_config`

Gets the current referral codes system configuration.

Returns a map with the current settings.

## Examples

    iex> PhoenixKit.Modules.Referrals.get_config()
    %{enabled: false, required: false}

# `get_max_codes_per_user`

Gets the maximum number of referral codes a single user can create.

Returns the system-wide limit for referral code creation per user.
Defaults to 10 if not set.

## Examples

    iex> PhoenixKit.Modules.Referrals.get_max_codes_per_user()
    10

# `get_max_uses_per_code`

Gets the maximum number of uses allowed per referral code.

Returns the system-wide limit for how many times a single referral code can be used.
Defaults to 100 if not set.

## Examples

    iex> PhoenixKit.Modules.Referrals.get_max_uses_per_code()
    100

# `get_system_stats`

Gets summary statistics for the referral codes system.

Returns counts and metrics useful for admin dashboards.

## Examples

    iex> PhoenixKit.Modules.Referrals.get_system_stats()
    %{total_codes: 10, active_codes: 8, total_usage: 150, codes_with_usage: 6}

# `get_usage_stats`

Gets usage statistics for a referral code.

## Examples

    iex> PhoenixKit.Modules.Referrals.get_usage_stats(code_uuid)
    %{total_uses: 5, unique_users: 3, last_used: ~U[...], recent_users: [...]}

# `list_codes`

Returns the list of referral codes ordered by creation date.

## Examples

    iex> PhoenixKit.Modules.Referrals.list_codes()
    [%PhoenixKit.Modules.Referrals{}, ...]

# `list_usage_for_code`

Lists all usage records for a referral code.

## Examples

    iex> PhoenixKit.Modules.Referrals.list_usage_for_code(code_uuid)
    [%PhoenixKit.Modules.Referrals.ReferralCodeUsage{}, ...]

# `list_valid_codes`

Gets codes that are currently valid for use.

Returns codes that are active, not expired, and haven't reached usage limits.

## Examples

    iex> PhoenixKit.Modules.Referrals.list_valid_codes()
    [%PhoenixKit.Modules.Referrals{}, ...]

# `required?`

Checks if referral codes are required for user registration.

Returns true if the "referral_codes_required" setting is true.

## Examples

    iex> PhoenixKit.Modules.Referrals.required?()
    false

# `set_max_codes_per_user`

Sets the maximum number of referral codes a single user can create.

Updates the system-wide limit for referral code creation per user.

## Examples

    iex> PhoenixKit.Modules.Referrals.set_max_codes_per_user(5)
    {:ok, %Setting{}}

# `set_max_uses_per_code`

Sets the maximum number of uses allowed per referral code.

Updates the system-wide limit for referral code usage.

## Examples

    iex> PhoenixKit.Modules.Referrals.set_max_uses_per_code(50)
    {:ok, %Setting{}}

# `set_required`

Sets whether referral codes are required for registration.

## Examples

    iex> PhoenixKit.Modules.Referrals.set_required(true)
    {:ok, %Setting{}}

    iex> PhoenixKit.Modules.Referrals.set_required(false)
    {:ok, %Setting{}}

# `update_code`

Updates a referral code.

## Examples

    iex> PhoenixKit.Modules.Referrals.update_code(code, %{description: "Updated"})
    {:ok, %PhoenixKit.Modules.Referrals{}}

    iex> PhoenixKit.Modules.Referrals.update_code(code, %{code: ""})
    {:error, %Ecto.Changeset{}}

# `usage_limit_reached?`

Checks if a referral code has reached its usage limit.

## Examples

    iex> PhoenixKit.Modules.Referrals.usage_limit_reached?(code)
    false

# `use_code`

Records usage of a referral code by a user.

Validates that the code is valid for use before recording the usage.
Updates the code's number_of_uses counter.

## Examples

    iex> PhoenixKit.Modules.Referrals.use_code("WELCOME2024", user_uuid)
    {:ok, %PhoenixKit.Modules.Referrals.ReferralCodeUsage{}}

    iex> PhoenixKit.Modules.Referrals.use_code("EXPIRED", user_uuid)
    {:error, :code_not_found}

# `user_used_code?`

Checks if a user has already used a specific referral code.

## Examples

    iex> PhoenixKit.Modules.Referrals.user_used_code?(user_uuid, code_uuid)
    false

# `valid_for_use?`

Checks if a referral code is currently valid for use.

A code is valid if:
- It exists and is active (status: true)
- It has not exceeded its maximum uses
- It has not expired

## Examples

    iex> PhoenixKit.Modules.Referrals.valid_for_use?(code)
    true

# `validate_user_code_limit`

Validates that a user hasn't exceeded their referral code creation limit.

Checks the current number of codes created by the user against the system limit.
Returns `{:ok, :valid}` if within limits, `{:error, reason}` if limit exceeded.

## Examples

    iex> PhoenixKit.Modules.Referrals.validate_user_code_limit(1)
    {:ok, :valid}

    iex> PhoenixKit.Modules.Referrals.validate_user_code_limit(1)
    {:error, "You have reached the maximum limit of 10 referral codes"}

---

*Consult [api-reference.md](api-reference.md) for complete listing*
