# Dashboard Redeem Controller - Data Specification

## File: `Modules/Dashboard/app/Http/Controllers/RedeemController.php`

### Method: `index()`

Controller harus mengirimkan data berikut ke view `dashboard::redeem`:

```php
public function index(Request $request)
{
    $user = auth()->user();
    
    // Get connected wallet (primary wallet first)
    $connected_wallet = \Modules\Wallet\Models\Wallet::with('platform')
        ->where('user_id', $user->id)
        ->where('is_primary', true)
        ->first();
    
    // If no primary wallet, get first available wallet
    if (!$connected_wallet) {
        $connected_wallet = \Modules\Wallet\Models\Wallet::with('platform')
            ->where('user_id', $user->id)
            ->first();
    }
    
    // Get total points (sum of all point transactions)
    $total_points = \Modules\Point\Models\Point::where('user_id', $user->id)
        ->sum('amount');
    
    // Get redeem history (coin conversions) with pagination
    $redeem_history = \Modules\Point\Models\CoinConversion::where('user_id', $user->id)
        ->orderBy('created_at', 'desc')
        ->paginate($request->get('per_page', 10));
    
    // Minimum points required to redeem
    $min_redeem_points = config('point.min_redeem_points', 10);
    
    return view('dashboard::redeem', [
        'title' => 'Redeem',
        'meta_description' => 'Tukar poin dengan koin',
        'connected_wallet' => $connected_wallet,
        'total_points' => $total_points,
        'redeem_history' => $redeem_history,
        'min_redeem_points' => $min_redeem_points,
    ]);
}
```

---

### Method: `process()`

Controller untuk memproses redeem poin:

```php
public function process(Request $request)
{
    $request->validate([
        'points_to_redeem' => 'required|integer|min:10',
    ]);
    
    $user = auth()->user();
    $points_to_redeem = $request->points_to_redeem;
    
    // Get conversion rate (e.g., 1 point = 1 coin)
    $conversion_rate = config('point.conversion_rate', 1.0);
    $coins_to_receive = (int) ($points_to_redeem * $conversion_rate);
    
    // Check if user has enough points
    $total_points = \Modules\Point\Models\Point::where('user_id', $user->id)
        ->sum('amount');
    
    if ($total_points < $points_to_redeem) {
        return back()->with('error', 'Poin Anda tidak cukup untuk melakukan redeem');
    }
    
    DB::beginTransaction();
    try {
        // Create coin conversion record
        $conversion = \Modules\Point\Models\CoinConversion::create([
            'user_id' => $user->id,
            'coins_converted' => $points_to_redeem,
            'points_received' => $coins_to_receive,
            'conversion_rate' => $conversion_rate,
        ]);
        
        // Deduct points
        \Modules\Point\Models\Point::create([
            'user_id' => $user->id,
            'amount' => -$points_to_redeem,
            'balance_after' => $total_points - $points_to_redeem,
            'source' => 'redeem',
            'description' => "Redeem {$points_to_redeem} poin menjadi {$coins_to_receive} koin",
        ]);
        
        // Add coins
        $current_coin_balance = \Modules\Point\Models\Coin::where('user_id', $user->id)
            ->sum('amount');
        
        \Modules\Point\Models\Coin::create([
            'user_id' => $user->id,
            'type' => 'earned',
            'amount' => $coins_to_receive,
            'balance_after' => $current_coin_balance + $coins_to_receive,
            'source' => 'point_conversion',
            'reference_type' => 'coin_conversions',
            'reference_id' => $conversion->id,
            'description' => "Konversi dari {$points_to_redeem} poin",
        ]);
        
        DB::commit();
        
        return back()->with('success', "Berhasil menukar {$points_to_redeem} poin menjadi {$coins_to_receive} koin!");
    } catch (\Exception $e) {
        DB::rollback();
        return back()->with('error', 'Terjadi kesalahan saat memproses redeem. Silakan coba lagi.');
    }
}
```

---

## Data Variables Required

### 1. **$connected_wallet** (Model Object or Null)
- **Source:** Table `wallets`
- **Relations:** 
  - `platform` (BelongsTo wallet_platforms)
- **Filters:**
  - `user_id` = current logged in user
  - `is_primary` = true (or first wallet if no primary)
- **Fields Used:**
  - `wallets.wallet_address` → displayed as "Address: {wallet_address}"
  - `wallet_platforms.name` → displayed as platform badge (INDODAX, METAMASK, etc.)
- **Display:** Header section "Wallet yang Terhubung"
- **Default:** If null, show "BELUM TERHUBUNG" and "-" for address

### 2. **$total_points** (Integer)
- **Source:** Table `points`
- **Calculation:** Sum of all `amount` from points table where:
  - `user_id` = current logged in user
- **Display:** Header section "Total Poin: {total_points} Poin"
- **Default:** 0 if no points
- **Note:** Used to check if user can redeem (must be >= $min_redeem_points)

### 3. **$redeem_history** (Paginated Collection)
- **Source:** Table `coin_conversions`
- **Relations:** 
  - `wallet` (BelongsTo wallets) - Optional
- **Filters:**
  - `user_id` = current logged in user
- **Order:** `created_at` DESC (newest first)
- **Pagination:** 10, 25, 50, or 100 per page (from request)
- **Fields Used:**
  - `coin_conversions.coins_converted` → points redeemed (displayed as negative)
  - `coin_conversions.points_received` → coins received (displayed with +)
  - `coin_conversions.created_at` → formatted as "d/m/Y"
  - `wallets.platform.name` → wallet platform name
- **Display:** Data table "Data Tabel Redeem Poin"

### 4. **$min_redeem_points** (Integer)
- **Source:** Config file `config/point.php`
- **Default:** 10
- **Usage:** 
  - Minimum points required to enable redeem button
  - Displayed in modal as conversion amount
- **Note:** Button disabled if `$total_points < $min_redeem_points`

---

## Database Tables Reference

### Related Tables:
1. **points** - Point transactions
   ```
   - id (BIGSERIAL)
   - user_id (BIGINT)
   - amount (INTEGER) - Can be positive or negative
   - balance_after (INTEGER)
   - source (VARCHAR) - 'game_reward', 'redeem', etc.
   - description (TEXT)
   - created_at (TIMESTAMP)
   ```

2. **coin_conversions** - Redeem history
   ```
   - id (BIGSERIAL)
   - user_id (BIGINT)
   - coins_converted (INTEGER) - Points spent
   - points_received (INTEGER) - Coins received
   - conversion_rate (DECIMAL)
   - created_at (TIMESTAMP)
   ```

3. **coins** - Coin transactions
   ```
   - id (BIGSERIAL)
   - user_id (BIGINT)
   - type (VARCHAR) - 'earned', 'spent', etc.
   - amount (INTEGER)
   - balance_after (INTEGER)
   - source (VARCHAR) - 'point_conversion', etc.
   - reference_type (VARCHAR) - 'coin_conversions'
   - reference_id (BIGINT) - coin_conversions.id
   - description (TEXT)
   - created_at (TIMESTAMP)
   ```

4. **wallets** - User wallets
   ```
   - id (BIGSERIAL)
   - user_id (BIGINT)
   - platform_id (BIGINT)
   - wallet_address (VARCHAR)
   - is_primary (BOOLEAN)
   ```

---

## Route Definition

Add to `Modules/Dashboard/routes/web.php`:

```php
Route::middleware(['auth'])->prefix('dashboard')->name('dashboard.')->group(function () {
    Route::get('/redeem', [RedeemController::class, 'index'])->name('redeem');
    Route::post('/redeem/process', [RedeemController::class, 'process'])->name('redeem.process');
});
```

---

## Configuration File

Create `config/point.php`:

```php
<?php

return [
    /*
    |--------------------------------------------------------------------------
    | Point System Configuration
    |--------------------------------------------------------------------------
    */

    // Minimum points required to redeem
    'min_redeem_points' => env('MIN_REDEEM_POINTS', 10),

    // Conversion rate: 1 point = X coins
    'conversion_rate' => env('POINT_CONVERSION_RATE', 1.0),

    // Maximum points that can be redeemed at once
    'max_redeem_points' => env('MAX_REDEEM_POINTS', 1000),
];
```

---

## Sample Controller Implementation

```php
<?php

namespace Modules\Dashboard\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Modules\Wallet\Models\Wallet;
use Modules\Point\Models\Point;
use Modules\Point\Models\Coin;
use Modules\Point\Models\CoinConversion;

class RedeemController extends Controller
{
    public function index(Request $request)
    {
        $user = auth()->user();
        
        // Get connected wallet
        $connected_wallet = Wallet::with('platform')
            ->where('user_id', $user->id)
            ->where('is_primary', true)
            ->first();
        
        if (!$connected_wallet) {
            $connected_wallet = Wallet::with('platform')
                ->where('user_id', $user->id)
                ->first();
        }
        
        // Get total points
        $total_points = Point::where('user_id', $user->id)
            ->sum('amount');
        
        // Get redeem history
        $redeem_history = CoinConversion::where('user_id', $user->id)
            ->orderBy('created_at', 'desc')
            ->paginate($request->get('per_page', 10));
        
        // Minimum redeem points
        $min_redeem_points = config('point.min_redeem_points', 10);
        
        return view('dashboard::redeem', [
            'title' => 'Redeem',
            'meta_description' => 'Tukar poin dengan koin',
            'connected_wallet' => $connected_wallet,
            'total_points' => $total_points,
            'redeem_history' => $redeem_history,
            'min_redeem_points' => $min_redeem_points,
        ]);
    }
    
    public function process(Request $request)
    {
        $request->validate([
            'points_to_redeem' => 'required|integer|min:' . config('point.min_redeem_points', 10),
        ]);
        
        $user = auth()->user();
        $points_to_redeem = $request->points_to_redeem;
        $conversion_rate = config('point.conversion_rate', 1.0);
        $coins_to_receive = (int) ($points_to_redeem * $conversion_rate);
        
        // Check balance
        $total_points = Point::where('user_id', $user->id)->sum('amount');
        
        if ($total_points < $points_to_redeem) {
            return back()->with('error', 'Poin Anda tidak cukup');
        }
        
        DB::beginTransaction();
        try {
            // Create conversion record
            $conversion = CoinConversion::create([
                'user_id' => $user->id,
                'coins_converted' => $points_to_redeem,
                'points_received' => $coins_to_receive,
                'conversion_rate' => $conversion_rate,
            ]);
            
            // Deduct points
            Point::create([
                'user_id' => $user->id,
                'amount' => -$points_to_redeem,
                'balance_after' => $total_points - $points_to_redeem,
                'source' => 'redeem',
                'description' => "Redeem poin menjadi koin",
            ]);
            
            // Add coins
            $coin_balance = Coin::where('user_id', $user->id)->sum('amount');
            Coin::create([
                'user_id' => $user->id,
                'type' => 'earned',
                'amount' => $coins_to_receive,
                'balance_after' => $coin_balance + $coins_to_receive,
                'source' => 'point_conversion',
                'reference_type' => 'coin_conversions',
                'reference_id' => $conversion->id,
                'description' => "Konversi dari poin",
            ]);
            
            DB::commit();
            return back()->with('success', "Berhasil menukar {$points_to_redeem} poin menjadi {$coins_to_receive} koin!");
        } catch (\Exception $e) {
            DB::rollback();
            return back()->with('error', 'Terjadi kesalahan');
        }
    }
}
```

---

## Model Relationships

### In `Modules\Point\Models\CoinConversion.php`:

```php
public function user()
{
    return $this->belongsTo(\App\Models\User::class);
}

public function wallet()
{
    // If you store wallet_id in coin_conversions table
    return $this->belongsTo(\Modules\Wallet\Models\Wallet::class);
}
```

---

## Notes for Backend Developer

1. **Wallet Required:** User must have connected wallet to redeem
2. **Minimum Points:** Check config `point.min_redeem_points` before allowing redeem
3. **Conversion Rate:** Configurable via `point.conversion_rate` (default 1:1)
4. **Transaction Safety:** Use DB transactions to ensure data consistency
5. **Balance Tracking:** Always update `balance_after` field in both points and coins tables
6. **Validation:** Validate user has sufficient points before processing
7. **Success Message:** Flash message after successful redeem
8. **Error Handling:** Rollback transaction on any error

---

**Last Updated:** January 8, 2026
