feat: add withdraw request functionality and UI components

This commit is contained in:
2026-08-27 02:39:57 +03:30
parent aeef95339d
commit 4ce663c669
115 changed files with 4064 additions and 315 deletions
@@ -0,0 +1,54 @@
<?php
use App\Enums\DocumentModalityEnum;
use App\Enums\InvoiceStatusEnum;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('invoices', function (Blueprint $table) {
$table->id();
$table->string('number')->unique();
$table->unsignedBigInteger('amount');
$table->string('status')->default(InvoiceStatusEnum::Pending->value);
$table->string('payment_method')->nullable();
$table->timestamp('paid_at')->nullable();
$table->timestamps();
$table->foreignId('document_id')->nullable()->constrained('documents')->cascadeOnDelete();
$table->foreignId('user_id')->constrained('users')->cascadeOnDelete();
});
DB::table('documents')->orderBy('id')->each(function ($document) {
$modality = DocumentModalityEnum::tryFrom($document->modality);
if (!$modality) {
return;
}
$id = DB::table('invoices')->insertGetId([
'number' => 'pending',
'amount' => $modality->price(),
'status' => InvoiceStatusEnum::Pending->value,
'document_id' => $document->id,
'user_id' => $document->requester_id,
'created_at' => $document->created_at,
'updated_at' => $document->created_at,
]);
DB::table('invoices')->where('id', $id)->update([
'number' => str_pad((string) $id, 5, '0', STR_PAD_LEFT),
]);
});
}
public function down(): void
{
Schema::dropIfExists('invoices');
}
};
@@ -0,0 +1,32 @@
<?php
use App\Enums\PaymentPurposeEnum;
use App\Enums\PaymentStatusEnum;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('payments', function (Blueprint $table) {
$table->id();
$table->string('track_id')->unique();
$table->unsignedBigInteger('amount');
$table->string('status')->default(PaymentStatusEnum::Pending->value);
$table->string('purpose')->default(PaymentPurposeEnum::Invoice->value);
$table->string('ref_number')->nullable();
$table->timestamp('verified_at')->nullable();
$table->timestamps();
$table->foreignId('invoice_id')->nullable()->constrained('invoices')->cascadeOnDelete();
$table->foreignId('payer_id')->constrained('users')->cascadeOnDelete();
});
}
public function down(): void
{
Schema::dropIfExists('payments');
}
};
@@ -0,0 +1,24 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('wallets', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('balance')->default(0);
$table->timestamps();
$table->foreignId('user_id')->unique()->constrained('users')->cascadeOnDelete();
});
}
public function down(): void
{
Schema::dropIfExists('wallets');
}
};
@@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->date('birthdate')->nullable()->after('fullname');
});
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('birthdate');
});
}
};
@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('wallet_transactions', function (Blueprint $table) {
$table->id();
$table->string('type');
$table->string('reason');
$table->unsignedBigInteger('amount');
$table->unsignedBigInteger('balance_after');
$table->string('description')->nullable();
$table->timestamps();
$table->foreignId('wallet_id')->constrained('wallets')->cascadeOnDelete();
$table->foreignId('invoice_id')->nullable()->constrained('invoices')->nullOnDelete();
$table->foreignId('payment_id')->nullable()->constrained('payments')->nullOnDelete();
});
}
public function down(): void
{
Schema::dropIfExists('wallet_transactions');
}
};
@@ -0,0 +1,25 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('reports', function (Blueprint $table) {
$table->text('technique')->nullable()->after('body');
$table->text('finding')->nullable()->after('technique');
$table->text('diagnose')->nullable()->after('finding');
$table->text('recommendation')->nullable()->after('diagnose');
});
}
public function down(): void
{
Schema::table('reports', function (Blueprint $table) {
$table->dropColumn(['technique', 'finding', 'diagnose', 'recommendation']);
});
}
};
@@ -0,0 +1,26 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('wallets', function (Blueprint $table) {
$table->dropForeign(['user_id']);
$table->foreignId('user_id')->nullable()->change();
$table->foreign('user_id')->references('id')->on('users')->cascadeOnDelete();
});
}
public function down(): void
{
Schema::table('wallets', function (Blueprint $table) {
$table->dropForeign(['user_id']);
$table->foreignId('user_id')->nullable(false)->change();
$table->foreign('user_id')->references('id')->on('users')->cascadeOnDelete();
});
}
};
@@ -0,0 +1,25 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('bank_cards', function (Blueprint $table) {
$table->id();
$table->string('card_number', 16);
$table->string('holder_name');
$table->timestamps();
$table->foreignId('user_id')->constrained('users')->cascadeOnDelete();
});
}
public function down(): void
{
Schema::dropIfExists('bank_cards');
}
};
@@ -0,0 +1,30 @@
<?php
use App\Enums\WithdrawRequestStatusEnum;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('withdraw_requests', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('amount');
$table->string('status')->default(WithdrawRequestStatusEnum::Pending->value)->index();
$table->text('admin_note')->nullable();
$table->timestamp('reviewed_at')->nullable();
$table->timestamps();
$table->foreignId('reviewed_by')->nullable()->constrained('users')->nullOnDelete();
$table->foreignId('user_id')->constrained('users')->cascadeOnDelete();
$table->foreignId('bank_card_id')->nullable()->constrained('bank_cards')->nullOnDelete();
});
}
public function down(): void
{
Schema::dropIfExists('withdraw_requests');
}
};
@@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('wallet_transactions', function (Blueprint $table) {
$table->foreignId('withdraw_request_id')->nullable()->after('payment_id')->constrained('withdraw_requests')->nullOnDelete();
});
}
public function down(): void
{
Schema::table('wallet_transactions', function (Blueprint $table) {
$table->dropConstrainedForeignId('withdraw_request_id');
});
}
};
+6
View File
@@ -109,6 +109,12 @@ class PermissionSeeder extends Seeder
'own' => 'دسترسی به شیفت های خود',
],
],
'withdrawals' => [
'label' => 'دسترسی به درخواست‌های برداشت',
'children' => [
'index' => 'دسترسی به لیست درخواست‌های برداشت',
],
],
];
foreach ($permissions as $key => $data) {
$parent = Permission::create([