Andrew Wallo 4 달 전
부모
커밋
9308f55e2f

+ 6
- 0
app/Filament/Company/Resources/Sales/ClientResource.php 파일 보기

@@ -3,6 +3,7 @@
3 3
 namespace App\Filament\Company\Resources\Sales;
4 4
 
5 5
 use App\Filament\Company\Resources\Sales\ClientResource\Pages;
6
+use App\Filament\Exports\Common\ClientExporter;
6 7
 use App\Filament\Forms\Components\AddressFields;
7 8
 use App\Filament\Forms\Components\CreateCurrencySelect;
8 9
 use App\Filament\Forms\Components\CustomSection;
@@ -247,6 +248,11 @@ class ClientResource extends Resource
247 248
     public static function table(Table $table): Table
248 249
     {
249 250
         return $table
251
+            ->headerActions([
252
+                Tables\Actions\ExportAction::make()
253
+                    ->slideOver()
254
+                    ->exporter(ClientExporter::class),
255
+            ])
250 256
             ->columns([
251 257
                 Columns::id(),
252 258
                 Tables\Columns\TextColumn::make('name')

+ 51
- 0
app/Filament/Exports/Common/ClientExporter.php 파일 보기

@@ -0,0 +1,51 @@
1
+<?php
2
+
3
+namespace App\Filament\Exports\Common;
4
+
5
+use App\Models\Common\Client;
6
+use Filament\Actions\Exports\ExportColumn;
7
+use Filament\Actions\Exports\Exporter;
8
+use Filament\Actions\Exports\Models\Export;
9
+
10
+class ClientExporter extends Exporter
11
+{
12
+    protected static ?string $model = Client::class;
13
+
14
+    public static function getColumns(): array
15
+    {
16
+        return [
17
+            ExportColumn::make('id')
18
+                ->label('ID'),
19
+            ExportColumn::make('company.name'),
20
+            ExportColumn::make('name'),
21
+            ExportColumn::make('currency_code'),
22
+            ExportColumn::make('account_number'),
23
+            ExportColumn::make('website'),
24
+            ExportColumn::make('notes'),
25
+            ExportColumn::make('primaryContact.full_name')
26
+                ->label('Primary Contact'),
27
+            ExportColumn::make('primaryContact.email')
28
+                ->label('Primary Contact Email'),
29
+            ExportColumn::make('primaryContact.phones')
30
+                ->label('Primary Contact Phones') // TODO: Format better
31
+                ->listAsJson(),
32
+            ExportColumn::make('billingAddress.address_string')
33
+                ->label('Billing Address'),
34
+            ExportColumn::make('created_by'),
35
+            ExportColumn::make('updated_by'),
36
+            ExportColumn::make('created_at'),
37
+            ExportColumn::make('updated_at'),
38
+        ];
39
+    }
40
+
41
+    public static function getCompletedNotificationBody(Export $export): string
42
+    {
43
+        $body = 'Your client export has completed and ' . number_format($export->successful_rows) . ' ' . str('row')->plural($export->successful_rows) . ' exported.';
44
+
45
+        if ($failedRowsCount = $export->getFailedRowsCount()) {
46
+            $body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to export.';
47
+        }
48
+
49
+        return $body;
50
+    }
51
+}

+ 1
- 0
app/Providers/Filament/CompanyPanelProvider.php 파일 보기

@@ -174,6 +174,7 @@ class CompanyPanelProvider extends PanelProvider
174 174
             })
175 175
             ->globalSearch(false)
176 176
             ->sidebarCollapsibleOnDesktop()
177
+            ->databaseNotifications()
177 178
             ->viteTheme('resources/css/filament/company/theme.css')
178 179
             ->brandLogo(static fn () => view('components.icons.logo'))
179 180
             ->tenant(Company::class)

+ 31
- 0
database/migrations/2025_06_06_024220_create_notifications_table.php 파일 보기

@@ -0,0 +1,31 @@
1
+<?php
2
+
3
+use Illuminate\Database\Migrations\Migration;
4
+use Illuminate\Database\Schema\Blueprint;
5
+use Illuminate\Support\Facades\Schema;
6
+
7
+return new class extends Migration
8
+{
9
+    /**
10
+     * Run the migrations.
11
+     */
12
+    public function up(): void
13
+    {
14
+        Schema::create('notifications', function (Blueprint $table) {
15
+            $table->uuid('id')->primary();
16
+            $table->string('type');
17
+            $table->morphs('notifiable');
18
+            $table->text('data');
19
+            $table->timestamp('read_at')->nullable();
20
+            $table->timestamps();
21
+        });
22
+    }
23
+
24
+    /**
25
+     * Reverse the migrations.
26
+     */
27
+    public function down(): void
28
+    {
29
+        Schema::dropIfExists('notifications');
30
+    }
31
+};

+ 35
- 0
database/migrations/2025_06_06_024242_create_imports_table.php 파일 보기

@@ -0,0 +1,35 @@
1
+<?php
2
+
3
+use Illuminate\Database\Migrations\Migration;
4
+use Illuminate\Database\Schema\Blueprint;
5
+use Illuminate\Support\Facades\Schema;
6
+
7
+return new class extends Migration
8
+{
9
+    /**
10
+     * Run the migrations.
11
+     */
12
+    public function up(): void
13
+    {
14
+        Schema::create('imports', function (Blueprint $table) {
15
+            $table->id();
16
+            $table->timestamp('completed_at')->nullable();
17
+            $table->string('file_name');
18
+            $table->string('file_path');
19
+            $table->string('importer');
20
+            $table->unsignedInteger('processed_rows')->default(0);
21
+            $table->unsignedInteger('total_rows');
22
+            $table->unsignedInteger('successful_rows')->default(0);
23
+            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
24
+            $table->timestamps();
25
+        });
26
+    }
27
+
28
+    /**
29
+     * Reverse the migrations.
30
+     */
31
+    public function down(): void
32
+    {
33
+        Schema::dropIfExists('imports');
34
+    }
35
+};

+ 35
- 0
database/migrations/2025_06_06_024243_create_exports_table.php 파일 보기

@@ -0,0 +1,35 @@
1
+<?php
2
+
3
+use Illuminate\Database\Migrations\Migration;
4
+use Illuminate\Database\Schema\Blueprint;
5
+use Illuminate\Support\Facades\Schema;
6
+
7
+return new class extends Migration
8
+{
9
+    /**
10
+     * Run the migrations.
11
+     */
12
+    public function up(): void
13
+    {
14
+        Schema::create('exports', function (Blueprint $table) {
15
+            $table->id();
16
+            $table->timestamp('completed_at')->nullable();
17
+            $table->string('file_disk');
18
+            $table->string('file_name')->nullable();
19
+            $table->string('exporter');
20
+            $table->unsignedInteger('processed_rows')->default(0);
21
+            $table->unsignedInteger('total_rows');
22
+            $table->unsignedInteger('successful_rows')->default(0);
23
+            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
24
+            $table->timestamps();
25
+        });
26
+    }
27
+
28
+    /**
29
+     * Reverse the migrations.
30
+     */
31
+    public function down(): void
32
+    {
33
+        Schema::dropIfExists('exports');
34
+    }
35
+};

+ 30
- 0
database/migrations/2025_06_06_024244_create_failed_import_rows_table.php 파일 보기

@@ -0,0 +1,30 @@
1
+<?php
2
+
3
+use Illuminate\Database\Migrations\Migration;
4
+use Illuminate\Database\Schema\Blueprint;
5
+use Illuminate\Support\Facades\Schema;
6
+
7
+return new class extends Migration
8
+{
9
+    /**
10
+     * Run the migrations.
11
+     */
12
+    public function up(): void
13
+    {
14
+        Schema::create('failed_import_rows', function (Blueprint $table) {
15
+            $table->id();
16
+            $table->json('data');
17
+            $table->foreignId('import_id')->constrained()->cascadeOnDelete();
18
+            $table->text('validation_error')->nullable();
19
+            $table->timestamps();
20
+        });
21
+    }
22
+
23
+    /**
24
+     * Reverse the migrations.
25
+     */
26
+    public function down(): void
27
+    {
28
+        Schema::dropIfExists('failed_import_rows');
29
+    }
30
+};

Loading…
취소
저장