base-api-scramble-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +140 -0
- package/docs/AI-GUIDE-COMPLETE.md +372 -0
- package/docs/EXCEL-EXPORT-SERVICE.md +349 -0
- package/docs/EXPORT-DATA-PROVIDERS.md +340 -0
- package/docs/EXPORT-TEMPLATES.md +459 -0
- package/docs/LARAVEL-API-TEST.md +355 -0
- package/docs/MAKE-EXPORT-EXCEL-COMMAND.md +215 -0
- package/docs/README.md +678 -0
- package/docs/STRUCTURE.md +540 -0
- package/docs/starting_point.md +423 -0
- package/index.js +968 -0
- package/package.json +17 -0
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
# KONTEKS & TUJUAN
|
|
2
|
+
Anda adalah Laravel Testing Expert. Tugas Anda: membuat automated feature tests untuk semua module/endpoint API di aplikasi Laravel, dengan pendekatan sistematis dan problem-solving otomatis.
|
|
3
|
+
|
|
4
|
+
# AUTHENTICATION & AUTHORIZATION
|
|
5
|
+
|
|
6
|
+
## Default Test Account
|
|
7
|
+
Aplikasi ini memiliki akun default dari seeder untuk testing:
|
|
8
|
+
- **Email:** admin@gmail.com
|
|
9
|
+
- **Password:** password
|
|
10
|
+
|
|
11
|
+
## Cara Mendapatkan Token untuk Authenticated Requests
|
|
12
|
+
```php
|
|
13
|
+
// Di dalam test method atau setUp()
|
|
14
|
+
$response = $this->postJson('/api/v1/login', [
|
|
15
|
+
'email' => 'admin@gmail.com',
|
|
16
|
+
'password' => 'password',
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
$this->token = $response->json('token');
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Penggunaan Token dalam Request
|
|
23
|
+
```php
|
|
24
|
+
// Untuk endpoint yang memerlukan authentication
|
|
25
|
+
$response = $this->withHeaders([
|
|
26
|
+
'Authorization' => 'Bearer ' . $this->token,
|
|
27
|
+
])->getJson('/api/v1/endpoint');
|
|
28
|
+
|
|
29
|
+
// ATAU menggunakan method helper (jika tersedia)
|
|
30
|
+
$response = $this->withToken($this->token)
|
|
31
|
+
->getJson('/api/v1/endpoint');
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Template Test Class dengan Authentication
|
|
35
|
+
```php
|
|
36
|
+
<?php
|
|
37
|
+
|
|
38
|
+
namespace Tests\Feature;
|
|
39
|
+
|
|
40
|
+
use Tests\TestCase;
|
|
41
|
+
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
42
|
+
use App\Models\{ModelName};
|
|
43
|
+
|
|
44
|
+
class {ModuleName}Test extends TestCase
|
|
45
|
+
{
|
|
46
|
+
use RefreshDatabase;
|
|
47
|
+
|
|
48
|
+
protected string $token;
|
|
49
|
+
|
|
50
|
+
protected function setUp(): void
|
|
51
|
+
{
|
|
52
|
+
parent::setUp();
|
|
53
|
+
|
|
54
|
+
// Seed database (jika diperlukan)
|
|
55
|
+
$this->seed();
|
|
56
|
+
|
|
57
|
+
// Get authentication token
|
|
58
|
+
$response = $this->postJson('/api/v1/login', [
|
|
59
|
+
'email' => 'admin@gmail.com',
|
|
60
|
+
'password' => 'password',
|
|
61
|
+
]);
|
|
62
|
+
|
|
63
|
+
$this->token = $response->json('token');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** @test */
|
|
67
|
+
public function it_can_list_{module}_with_pagination()
|
|
68
|
+
{
|
|
69
|
+
$response = $this->withHeaders([
|
|
70
|
+
'Authorization' => 'Bearer ' . $this->token,
|
|
71
|
+
])->getJson('/api/v1/{endpoint}');
|
|
72
|
+
|
|
73
|
+
$response->assertStatus(200);
|
|
74
|
+
// ... assertions lainnya
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ... test methods lainnya
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Strategi Authentication dalam Test
|
|
82
|
+
|
|
83
|
+
1. **Setup Method (Recommended):**
|
|
84
|
+
- Login sekali di `setUp()` untuk semua test dalam class
|
|
85
|
+
- Efisien untuk multiple test methods
|
|
86
|
+
- Token tersedia di semua test methods via `$this->token`
|
|
87
|
+
|
|
88
|
+
2. **Per Test Method:**
|
|
89
|
+
- Login di setiap test method jika butuh kondisi berbeda
|
|
90
|
+
- Gunakan jika test memerlukan user dengan role/permission berbeda
|
|
91
|
+
|
|
92
|
+
3. **Helper Method (Optional):**
|
|
93
|
+
```php
|
|
94
|
+
protected function authenticatedRequest(string $method, string $uri, array $data = [])
|
|
95
|
+
{
|
|
96
|
+
return $this->withHeaders([
|
|
97
|
+
'Authorization' => 'Bearer ' . $this->token,
|
|
98
|
+
])->json($method, $uri, $data);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Penggunaan:
|
|
102
|
+
$response = $this->authenticatedRequest('GET', '/api/v1/endpoint');
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
# LANGKAH KERJA SISTEMATIS
|
|
106
|
+
|
|
107
|
+
## FASE 1: DISCOVERY & MAPPING
|
|
108
|
+
1. Jalankan `php artisan route:list --json` untuk mendapatkan daftar lengkap routes
|
|
109
|
+
2. Identifikasi routes yang memerlukan authentication (middleware: auth, auth:sanctum, dll)
|
|
110
|
+
3. Kelompokkan routes berdasarkan module/resource (prefix atau controller)
|
|
111
|
+
4. Identifikasi struktur CRUD untuk setiap module:
|
|
112
|
+
- Index/List (GET)
|
|
113
|
+
- Show/Detail (GET)
|
|
114
|
+
- Store/Create (POST)
|
|
115
|
+
- Update (PUT/PATCH)
|
|
116
|
+
- Delete (DELETE)
|
|
117
|
+
- Custom endpoints lainnya
|
|
118
|
+
|
|
119
|
+
## FASE 2: ANALISIS PER MODULE
|
|
120
|
+
Sebelum membuat test untuk setiap module, lakukan analisis:
|
|
121
|
+
|
|
122
|
+
1. **Authentication Requirements:**
|
|
123
|
+
- Cek apakah endpoint memerlukan authentication
|
|
124
|
+
- Identifikasi middleware yang digunakan (auth:sanctum, auth:api, dll)
|
|
125
|
+
- Catat jika ada role/permission tertentu yang diperlukan
|
|
126
|
+
|
|
127
|
+
2. **Request Requirements:**
|
|
128
|
+
- Buka file FormRequest atau validasi di Controller
|
|
129
|
+
- Catat semua field yang required, optional, dan rule validasinya
|
|
130
|
+
- Identifikasi field relationship (belongsTo, hasMany, dll)
|
|
131
|
+
|
|
132
|
+
3. **Response Structure:**
|
|
133
|
+
- Periksa struktur response dari Controller/Resource
|
|
134
|
+
- Identifikasi field yang di-return di response JSON
|
|
135
|
+
- Catat struktur nested data (relationships yang di-load)
|
|
136
|
+
|
|
137
|
+
4. **Dependencies:**
|
|
138
|
+
- Identifikasi model dependencies (foreign keys)
|
|
139
|
+
- Tentukan urutan factory/seeding yang diperlukan
|
|
140
|
+
- Catat middleware atau authorization yang digunakan
|
|
141
|
+
|
|
142
|
+
## FASE 3: IMPLEMENTASI TEST PER MODULE
|
|
143
|
+
|
|
144
|
+
Untuk setiap module, buat test file dengan struktur lengkap:
|
|
145
|
+
|
|
146
|
+
### Template Test Structure:
|
|
147
|
+
```php
|
|
148
|
+
<?php
|
|
149
|
+
|
|
150
|
+
namespace Tests\Feature;
|
|
151
|
+
|
|
152
|
+
use Tests\TestCase;
|
|
153
|
+
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
154
|
+
use App\Models\{ModelName};
|
|
155
|
+
// Import models lain yang dibutuhkan
|
|
156
|
+
|
|
157
|
+
class {ModuleName}Test extends TestCase
|
|
158
|
+
{
|
|
159
|
+
use RefreshDatabase;
|
|
160
|
+
|
|
161
|
+
protected string $token;
|
|
162
|
+
|
|
163
|
+
protected function setUp(): void
|
|
164
|
+
{
|
|
165
|
+
parent::setUp();
|
|
166
|
+
|
|
167
|
+
// Seed database (pastikan UserSeeder dijalankan)
|
|
168
|
+
$this->seed();
|
|
169
|
+
|
|
170
|
+
// Login to get authentication token
|
|
171
|
+
$response = $this->postJson('/api/v1/login', [
|
|
172
|
+
'email' => 'admin@gmail.com',
|
|
173
|
+
'password' => 'password',
|
|
174
|
+
]);
|
|
175
|
+
|
|
176
|
+
$this->token = $response->json('token');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** @test */
|
|
180
|
+
public function it_requires_authentication()
|
|
181
|
+
{
|
|
182
|
+
// Test tanpa token harus return 401
|
|
183
|
+
$response = $this->getJson('/api/v1/{endpoint}');
|
|
184
|
+
$response->assertStatus(401);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** @test */
|
|
188
|
+
public function it_can_list_{module}_with_pagination()
|
|
189
|
+
{
|
|
190
|
+
// Setup: Create sample data
|
|
191
|
+
// Act: Hit endpoint with token
|
|
192
|
+
$response = $this->withHeaders([
|
|
193
|
+
'Authorization' => 'Bearer ' . $this->token,
|
|
194
|
+
])->getJson('/api/v1/{endpoint}');
|
|
195
|
+
|
|
196
|
+
// Assert: Check response structure, pagination, data
|
|
197
|
+
$response->assertStatus(200);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** @test */
|
|
201
|
+
public function it_can_show_{module}_detail()
|
|
202
|
+
{
|
|
203
|
+
// Test dengan data valid dan token
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** @test */
|
|
207
|
+
public function it_returns_404_when_{module}_not_found()
|
|
208
|
+
{
|
|
209
|
+
// Test edge case dengan authentication
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** @test */
|
|
213
|
+
public function it_can_create_{module}_with_valid_data()
|
|
214
|
+
{
|
|
215
|
+
// Setup: Prepare valid payload sesuai FormRequest
|
|
216
|
+
$payload = [
|
|
217
|
+
// ... data sesuai validation rules
|
|
218
|
+
];
|
|
219
|
+
|
|
220
|
+
// Act: POST request with authentication
|
|
221
|
+
$response = $this->withHeaders([
|
|
222
|
+
'Authorization' => 'Bearer ' . $this->token,
|
|
223
|
+
])->postJson('/api/v1/{endpoint}', $payload);
|
|
224
|
+
|
|
225
|
+
// Assert: Check 201, response structure, database
|
|
226
|
+
$response->assertStatus(201);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** @test */
|
|
230
|
+
public function it_validates_required_fields_when_creating_{module}()
|
|
231
|
+
{
|
|
232
|
+
// Test validation untuk setiap required field dengan auth
|
|
233
|
+
$response = $this->withHeaders([
|
|
234
|
+
'Authorization' => 'Bearer ' . $this->token,
|
|
235
|
+
])->postJson('/api/v1/{endpoint}', []);
|
|
236
|
+
|
|
237
|
+
$response->assertStatus(422);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** @test */
|
|
241
|
+
public function it_can_update_{module}_with_valid_data()
|
|
242
|
+
{
|
|
243
|
+
// Test update dengan partial/full data dan authentication
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/** @test */
|
|
247
|
+
public function it_can_delete_{module}()
|
|
248
|
+
{
|
|
249
|
+
// Test soft delete atau hard delete dengan authentication
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Tambahkan test untuk custom endpoints jika ada
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Assertion Checklist untuk Setiap Test:
|
|
257
|
+
- ✅ Authentication check (401 without token)
|
|
258
|
+
- ✅ HTTP Status Code (200, 201, 204, 404, 422, dll)
|
|
259
|
+
- ✅ Response JSON structure (`assertJsonStructure`)
|
|
260
|
+
- ✅ Response data accuracy (`assertJsonFragment`, `assertJson`)
|
|
261
|
+
- ✅ Database changes (`assertDatabaseHas`, `assertDatabaseMissing`)
|
|
262
|
+
- ✅ Database count (`assertDatabaseCount`)
|
|
263
|
+
- ✅ Validation error messages (untuk negative tests)
|
|
264
|
+
|
|
265
|
+
## FASE 4: PROBLEM SOLVING OTOMATIS
|
|
266
|
+
|
|
267
|
+
Jika test GAGAL, lakukan troubleshooting sistematis:
|
|
268
|
+
|
|
269
|
+
1. **Analisis Error Message:**
|
|
270
|
+
- Baca error stack trace dengan teliti
|
|
271
|
+
- Identifikasi root cause (validation, missing data, logic error, auth issue)
|
|
272
|
+
|
|
273
|
+
2. **Authentication Issues:**
|
|
274
|
+
- Jika error 401: Pastikan token sudah diset dengan benar
|
|
275
|
+
- Jika error 403: Check role/permission requirements
|
|
276
|
+
- Jika token null: Pastikan seeder sudah dijalankan dan login berhasil
|
|
277
|
+
- Verify endpoint login (`/api/v1/login`) dan token location di response
|
|
278
|
+
|
|
279
|
+
3. **Perbaikan Bertahap:**
|
|
280
|
+
- Jika authentication error: Periksa token dan header Authorization
|
|
281
|
+
- Jika validation error: Sesuaikan payload dengan FormRequest rules
|
|
282
|
+
- Jika database error: Periksa foreign key constraints dan dependencies
|
|
283
|
+
- Jika response mismatch: Update assertion atau perbaiki Controller
|
|
284
|
+
|
|
285
|
+
4. **Iterasi & Verifikasi:**
|
|
286
|
+
- Perbaiki satu issue pada satu waktu
|
|
287
|
+
- Re-run test setelah setiap perbaikan
|
|
288
|
+
- Jika masih gagal, cek file Controller dan Model terkait
|
|
289
|
+
- Dokumentasikan perubahan yang dilakukan
|
|
290
|
+
|
|
291
|
+
5. **Edge Cases:**
|
|
292
|
+
- Test tanpa authentication (should return 401)
|
|
293
|
+
- Test dengan invalid/expired token
|
|
294
|
+
- Test dengan data kosong
|
|
295
|
+
- Test dengan data invalid (wrong type, format)
|
|
296
|
+
- Test dengan foreign key yang tidak exist
|
|
297
|
+
- Test authorization (jika ada role/permission)
|
|
298
|
+
|
|
299
|
+
## FASE 5: EKSEKUSI BERTAHAP
|
|
300
|
+
|
|
301
|
+
**PENTING - RULES EKSEKUSI:**
|
|
302
|
+
1. ⚠️ Pastikan seeder sudah dijalankan (`$this->seed()` atau `php artisan db:seed`)
|
|
303
|
+
2. ⚠️ Verify akun admin@gmail.com tersedia dan bisa login
|
|
304
|
+
3. ⚠️ Kerjakan SATU module FULL hingga SEMUA test PASS
|
|
305
|
+
4. ⚠️ Jangan lanjut ke module berikutnya jika masih ada test yang FAILED
|
|
306
|
+
5. ⚠️ Jalankan `php artisan test --filter={ModuleName}Test` untuk verifikasi
|
|
307
|
+
6. ⚠️ Setelah ALL PASS, commit perubahan sebelum lanjut module berikutnya
|
|
308
|
+
7. ⚠️ Ulangi proses untuk module berikutnya
|
|
309
|
+
|
|
310
|
+
## FASE 6: REPORTING
|
|
311
|
+
|
|
312
|
+
Setelah menyelesaikan setiap module, buat summary:
|
|
313
|
+
```
|
|
314
|
+
✅ Module: {Nama Module}
|
|
315
|
+
- Total Endpoints: X
|
|
316
|
+
- Total Tests: X (including authentication tests)
|
|
317
|
+
- Status: ALL PASSED
|
|
318
|
+
- Coverage: Authentication + List/Show/Create/Update/Delete + custom endpoints
|
|
319
|
+
- Waktu Eksekusi: X seconds
|
|
320
|
+
- Authentication: ✅ Token-based (Sanctum/Passport)
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
# MODULE YANG DIABAIKAN (SKIP)
|
|
324
|
+
- User
|
|
325
|
+
- Permissions
|
|
326
|
+
- Roles
|
|
327
|
+
- Telescope
|
|
328
|
+
- Activity Log
|
|
329
|
+
- Post
|
|
330
|
+
- Label
|
|
331
|
+
|
|
332
|
+
Jika menemukan routes dari module ini, SKIP dan lanjut ke module berikutnya.
|
|
333
|
+
|
|
334
|
+
# OUTPUT YANG DIHARAPKAN
|
|
335
|
+
1. Test file PHP yang executable dan comprehensive
|
|
336
|
+
2. Semua test PASS tanpa error
|
|
337
|
+
3. Authentication handling yang proper di setiap test
|
|
338
|
+
4. Coverage minimal: Authentication check + CRUD lengkap per module
|
|
339
|
+
5. Code yang clean, readable, dan well-documented
|
|
340
|
+
6. Problem solving dilakukan secara otomatis hingga test berhasil
|
|
341
|
+
|
|
342
|
+
# VALIDASI AKHIR
|
|
343
|
+
Sebelum declare selesai:
|
|
344
|
+
- [ ] Seeder berhasil dijalankan dan akun admin tersedia
|
|
345
|
+
- [ ] Login endpoint working dan return token dengan benar
|
|
346
|
+
- [ ] Token digunakan di semua authenticated requests
|
|
347
|
+
- [ ] Semua module (kecuali yang di-skip) sudah memiliki test
|
|
348
|
+
- [ ] Semua test berstatus PASSED
|
|
349
|
+
- [ ] Authentication tests included (401 without token)
|
|
350
|
+
- [ ] Response structure sesuai dengan actual API
|
|
351
|
+
- [ ] Request payload sesuai dengan validation rules
|
|
352
|
+
- [ ] Database assertions akurat
|
|
353
|
+
- [ ] Jalankan `php artisan test` untuk final check
|
|
354
|
+
|
|
355
|
+
Mulai dengan menjalankan `php artisan route:list --json` dan laporkan hasilnya.
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# Make Export Excel Command
|
|
2
|
+
|
|
3
|
+
Command untuk generate controller dan DataProvider export Excel secara otomatis.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
php artisan make:export-excel {namaExport}
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### Contoh
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
php artisan make:export-excel Category
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Akan menghasilkan:
|
|
18
|
+
- **DataProvider**: `app/Exports/DataProviders/CategoryExportDataProvider.php`
|
|
19
|
+
- **Controller**: `app/Http/Controllers/Api/V1/CategoryExportController.php`
|
|
20
|
+
|
|
21
|
+
## File yang di-generate
|
|
22
|
+
|
|
23
|
+
### 1. DataProvider (`CategoryExportDataProvider.php`)
|
|
24
|
+
|
|
25
|
+
DataProvider akan otomatis:
|
|
26
|
+
- Membaca data dari model yang sesuai (misal: `Category` model)
|
|
27
|
+
- Menyediakan method `getRawData()` untuk query data
|
|
28
|
+
- Menyediakan method `getHeaders()` untuk header kolom
|
|
29
|
+
- Menyediakan method `getDataMapper()` untuk mapping data
|
|
30
|
+
- Support filtering via Request (search, status, dll)
|
|
31
|
+
|
|
32
|
+
**Contoh struktur:**
|
|
33
|
+
```php
|
|
34
|
+
namespace App\Exports\DataProviders;
|
|
35
|
+
|
|
36
|
+
use App\Models\Category;
|
|
37
|
+
use Illuminate\Http\Request;
|
|
38
|
+
|
|
39
|
+
class CategoryExportDataProvider implements ExportDataProviderInterface
|
|
40
|
+
{
|
|
41
|
+
private Request $request;
|
|
42
|
+
|
|
43
|
+
public function __construct(Request $request)
|
|
44
|
+
{
|
|
45
|
+
$this->request = $request;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public function getRawData($filters = null): array
|
|
49
|
+
{
|
|
50
|
+
$query = Category::query();
|
|
51
|
+
|
|
52
|
+
// Apply filters dari request
|
|
53
|
+
if ($this->request->filled('search')) {
|
|
54
|
+
$query->where('name', 'like', '%' . $this->request->search . '%');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return $query->get()->toArray();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public function getHeaders(): array
|
|
61
|
+
{
|
|
62
|
+
return ['ID', 'Name', 'Created At', 'Updated At'];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public function getDataMapper(): array
|
|
66
|
+
{
|
|
67
|
+
return [
|
|
68
|
+
'id',
|
|
69
|
+
'name',
|
|
70
|
+
'created_at' => function($item) {
|
|
71
|
+
return date('Y-m-d H:i:s', strtotime($item['created_at']));
|
|
72
|
+
},
|
|
73
|
+
'updated_at' => function($item) {
|
|
74
|
+
return date('Y-m-d H:i:s', strtotime($item['updated_at']));
|
|
75
|
+
},
|
|
76
|
+
];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
public function getOptions(): array
|
|
80
|
+
{
|
|
81
|
+
return [
|
|
82
|
+
'report_title' => 'Category Export Report',
|
|
83
|
+
'include_summary' => true,
|
|
84
|
+
'auto_size' => true,
|
|
85
|
+
'bold_header' => true,
|
|
86
|
+
'freeze_header' => true,
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 2. Controller (`CategoryExportController.php`)
|
|
93
|
+
|
|
94
|
+
Controller akan otomatis:
|
|
95
|
+
- Berada di namespace `App\Http\Controllers\Api\V1`
|
|
96
|
+
- Memiliki method `export(Request $request)`
|
|
97
|
+
- Menggunakan DataProvider untuk get data
|
|
98
|
+
- Menggunakan `FlexibleExport` template
|
|
99
|
+
- Support download langsung atau save to file
|
|
100
|
+
|
|
101
|
+
**Contoh struktur:**
|
|
102
|
+
```php
|
|
103
|
+
namespace App\Http\Controllers\Api\V1;
|
|
104
|
+
|
|
105
|
+
use App\Http\Controllers\Controller;
|
|
106
|
+
use App\Exports\Templates\FlexibleExport;
|
|
107
|
+
use App\Exports\DataProviders\CategoryExportDataProvider;
|
|
108
|
+
use Illuminate\Http\Request;
|
|
109
|
+
|
|
110
|
+
class CategoryExportController extends Controller
|
|
111
|
+
{
|
|
112
|
+
public function export(Request $request)
|
|
113
|
+
{
|
|
114
|
+
try {
|
|
115
|
+
$provider = new CategoryExportDataProvider($request);
|
|
116
|
+
|
|
117
|
+
$rawData = $provider->getRawData();
|
|
118
|
+
$headers = $provider->getHeaders();
|
|
119
|
+
$dataMapper = $provider->getDataMapper();
|
|
120
|
+
$options = $provider->getOptions();
|
|
121
|
+
|
|
122
|
+
$export = FlexibleExport::create($rawData, $headers, array_merge($options, [
|
|
123
|
+
'data_mapper' => $dataMapper
|
|
124
|
+
]));
|
|
125
|
+
|
|
126
|
+
if ($request->boolean('download', true)) {
|
|
127
|
+
return $export->download();
|
|
128
|
+
} else {
|
|
129
|
+
$filePath = $export->toFile();
|
|
130
|
+
return response()->json([
|
|
131
|
+
'success' => true,
|
|
132
|
+
'message' => 'Category export created successfully',
|
|
133
|
+
'file_path' => $filePath,
|
|
134
|
+
'filename' => $export->getFilename()
|
|
135
|
+
]);
|
|
136
|
+
}
|
|
137
|
+
} catch (\Exception $e) {
|
|
138
|
+
return response()->json([
|
|
139
|
+
'success' => false,
|
|
140
|
+
'message' => 'Export failed: ' . $e->getMessage()
|
|
141
|
+
], 500);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Langkah Setelah Generate
|
|
148
|
+
|
|
149
|
+
1. **Pastikan Model Ada**
|
|
150
|
+
- Command akan menggunakan nama yang sama untuk model
|
|
151
|
+
- Contoh: `make:export-excel Category` akan menggunakan model `App\Models\Category`
|
|
152
|
+
|
|
153
|
+
2. **Tambahkan Route**
|
|
154
|
+
|
|
155
|
+
Edit file `routes/api_v1.php`:
|
|
156
|
+
```php
|
|
157
|
+
use App\Http\Controllers\Api\V1\CategoryExportController;
|
|
158
|
+
|
|
159
|
+
Route::get('categories/export', [CategoryExportController::class, 'export']);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
3. **Customize DataProvider** (Optional)
|
|
163
|
+
|
|
164
|
+
Sesuaikan logic di DataProvider:
|
|
165
|
+
- Tambah filter custom
|
|
166
|
+
- Ubah field yang di-export
|
|
167
|
+
- Sesuaikan header
|
|
168
|
+
- Tambah relationship jika perlu
|
|
169
|
+
|
|
170
|
+
## Contoh Penggunaan API
|
|
171
|
+
|
|
172
|
+
### Export dengan download langsung
|
|
173
|
+
```bash
|
|
174
|
+
GET /api/v1/categories/export
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Export save to file
|
|
178
|
+
```bash
|
|
179
|
+
GET /api/v1/categories/export?download=false
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Export dengan filter
|
|
183
|
+
```bash
|
|
184
|
+
GET /api/v1/categories/export?search=electronics
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Fitur
|
|
188
|
+
|
|
189
|
+
✅ Auto-generate DataProvider dengan model binding
|
|
190
|
+
✅ Auto-generate Controller di folder `api/v1`
|
|
191
|
+
✅ Support filtering via Request
|
|
192
|
+
✅ Support download atau save to file
|
|
193
|
+
✅ Menggunakan FlexibleExport template
|
|
194
|
+
✅ Include header styling (bold, freeze)
|
|
195
|
+
✅ Auto-size columns
|
|
196
|
+
✅ Customizable data mapping
|
|
197
|
+
|
|
198
|
+
## Tips
|
|
199
|
+
|
|
200
|
+
1. **Naming Convention**:
|
|
201
|
+
- Command akan menghapus suffix "Export" jika ada
|
|
202
|
+
- `make:export-excel CategoryExport` = `make:export-excel Category`
|
|
203
|
+
|
|
204
|
+
2. **Model Detection**:
|
|
205
|
+
- Model harus ada di `App\Models\{Name}`
|
|
206
|
+
- Pastikan model sudah dibuat sebelumnya
|
|
207
|
+
|
|
208
|
+
3. **Customization**:
|
|
209
|
+
- Edit DataProvider untuk logic export yang lebih complex
|
|
210
|
+
- Tambah relationship dengan eager loading
|
|
211
|
+
- Tambah filter custom sesuai kebutuhan
|
|
212
|
+
|
|
213
|
+
4. **Route Naming**:
|
|
214
|
+
- Recommended format: `{plural-resource}/export`
|
|
215
|
+
- Example: `products/export`, `users/export`, `categories/export`
|