diff --git a/app/Filament/Resources/AffiliateResource.php b/app/Filament/Resources/AffiliateResource.php index aef1940f..1dfe9f5b 100644 --- a/app/Filament/Resources/AffiliateResource.php +++ b/app/Filament/Resources/AffiliateResource.php @@ -4,11 +4,13 @@ use App\Filament\Resources\AffiliateResource\Pages; use App\Models\Affiliate; +use App\Services\AffiliateReportingService; use Filament\Forms; use Filament\Forms\Form; use Filament\Resources\Resource; use Filament\Tables\Table; use Filament\Tables; +use Filament\Tables\Actions\Action; class AffiliateResource extends Resource { @@ -38,6 +40,10 @@ public static function form(Form $form): Form 'inactive' => 'Inactive', ]) ->required(), + Forms\Components\TextInput::make('total_earnings') + ->disabled() + ->label('Total Earnings') + ->formatStateUsing(fn ($state) => '$' . number_format($state, 2)), ]); } @@ -49,6 +55,40 @@ public static function table(Table $table): Table Tables\Columns\TextColumn::make('code'), Tables\Columns\TextColumn::make('commission_rate'), Tables\Columns\TextColumn::make('status'), + Tables\Columns\TextColumn::make('total_earnings') + ->money('usd') + ->sortable(), + ]) + ->filters([ + // + ]) + ->actions([ + Tables\Actions\EditAction::make(), + Action::make('generateReport') + ->label('Generate Report') + ->icon('heroicon-o-document-report') + ->action(function (Affiliate $record, AffiliateReportingService $reportingService) { + $report = $reportingService->generateReport($record, now()->subMonth(), now()); + // Here you can return the report data or redirect to a report view + return redirect()->route('affiliate.report', $report); + }), + ]) + ->bulkActions([ + Tables\Actions\DeleteBulkAction::make(), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('user.name'), + Tables\Columns\TextColumn::make('code'), + Tables\Columns\TextColumn::make('commission_rate'), + Tables\Columns\TextColumn::make('status'), + Tables\Columns\TextColumn::make('total_earnings') + ->money('usd') + ->sortable(), ]) ->filters([ // diff --git a/app/Models/Affiliate.php b/app/Models/Affiliate.php index ec53facd..b7bb7e61 100644 --- a/app/Models/Affiliate.php +++ b/app/Models/Affiliate.php @@ -14,6 +14,11 @@ class Affiliate extends Model 'code', 'commission_rate', 'status', + 'custom_rates', + ]; + + protected $casts = [ + 'custom_rates' => 'array', ]; public function user() @@ -30,4 +35,17 @@ public function payments() { return $this->hasMany(Payment::class); } + + public function getCommissionRate($productId = null, $categoryId = null) + { + if ($productId && isset($this->custom_rates['products'][$productId])) { + return $this->custom_rates['products'][$productId]; + } + + if ($categoryId && isset($this->custom_rates['categories'][$categoryId])) { + return $this->custom_rates['categories'][$categoryId]; + } + + return $this->commission_rate; + } } \ No newline at end of file diff --git a/app/Services/AffiliateReportingService.php b/app/Services/AffiliateReportingService.php new file mode 100644 index 00000000..abdba577 --- /dev/null +++ b/app/Services/AffiliateReportingService.php @@ -0,0 +1,31 @@ +startOfDay(); + $endDate = Carbon::parse($endDate)->endOfDay(); + + $transactions = $affiliate->transactions() + ->whereBetween('created_at', [$startDate, $endDate]) + ->get(); + + $totalEarnings = $transactions->where('type', 'commission')->sum('amount'); + $totalReferrals = $affiliate->referrals()->whereBetween('created_at', [$startDate, $endDate])->count(); + + return [ + 'affiliate' => $affiliate, + 'start_date' => $startDate->toDateString(), + 'end_date' => $endDate->toDateString(), + 'total_earnings' => $totalEarnings, + 'total_referrals' => $totalReferrals, + 'transactions' => $transactions, + ]; + } +} \ No newline at end of file diff --git a/app/Services/AffiliateService.php b/app/Services/AffiliateService.php index 2a357309..834b50f4 100644 --- a/app/Services/AffiliateService.php +++ b/app/Services/AffiliateService.php @@ -13,14 +13,23 @@ public function processAffiliateReward(Payment $payment) $referrer = $user->referrer; if ($referrer && $referrer->status === 'active') { - $commissionAmount = $payment->amount * ($referrer->commission_rate / 100); + $product = $payment->invoice->items->first()->product; + $commissionRate = $referrer->getCommissionRate($product->id, $product->category_id); + $commissionAmount = $payment->amount * ($commissionRate / 100); $payment->update([ 'affiliate_id' => $referrer->id, 'affiliate_commission' => $commissionAmount, ]); - // Here you can add logic to credit the affiliate's account or create a separate transaction + $referrer->increment('total_earnings', $commissionAmount); + + // Create a transaction record for the affiliate + $referrer->transactions()->create([ + 'amount' => $commissionAmount, + 'type' => 'commission', + 'description' => "Commission for payment #{$payment->id}", + ]); } } } \ No newline at end of file diff --git a/database/migrations/2023_05_25_000000_create_affiliates_table.php b/database/migrations/2023_05_25_000000_create_affiliates_table.php index 6d5e6b0d..d51ffa88 100644 --- a/database/migrations/2023_05_25_000000_create_affiliates_table.php +++ b/database/migrations/2023_05_25_000000_create_affiliates_table.php @@ -14,6 +14,8 @@ public function up() $table->string('code')->unique(); $table->decimal('commission_rate', 5, 2); $table->enum('status', ['active', 'inactive'])->default('active'); + $table->json('custom_rates')->nullable(); + $table->decimal('total_earnings', 10, 2)->default(0); $table->timestamps(); }); }