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.
@@ -0,0 +1,349 @@
1
+ # Excel Export Service Documentation
2
+
3
+ Service ini menyediakan fitur export Excel yang lengkap dengan dukungan multiple sheets, multiple tables, custom styling, chunking untuk data besar, dan informasi export yang detail.
4
+
5
+ ## Features
6
+
7
+ - ✅ **Multiple Sheets**: Export ke beberapa sheet dalam satu file
8
+ - ✅ **Multiple Tables**: Export beberapa tabel dalam satu sheet
9
+ - ✅ **Custom Styling**: Default styling dan custom styling
10
+ - ✅ **Chunking**: Otomatis memproses data dalam chunk 1000 records
11
+ - ✅ **Export Info**: Header informasi perusahaan, user, tanggal export
12
+ - ✅ **Memory Management**: Manajemen memory dan execution time
13
+ - ✅ **Flexible Headers**: Support custom headers dan column mapping
14
+
15
+ ## Configuration
16
+
17
+ ### Environment Variables
18
+ Tambahkan variabel berikut ke `.env`:
19
+
20
+ ```env
21
+ # Export Configuration
22
+ EXPORT_AUTHOR_NAME="System Administrator"
23
+ EXPORT_AUTHOR_EMAIL="admin@company.com"
24
+ EXPORT_COMPANY_NAME="Your Company Name"
25
+ EXPORT_COMPANY_ADDRESS="Company Address"
26
+ EXPORT_COMPANY_PHONE="+62-xxx-xxx-xxx"
27
+ EXPORT_COMPANY_WEBSITE="https://company.com"
28
+ EXPORT_CHUNK_SIZE=1000
29
+ EXPORT_MEMORY_LIMIT=512M
30
+ EXPORT_MAX_EXECUTION_TIME=300
31
+ EXPORT_TEMP_DIRECTORY=storage/exports/temp
32
+ EXPORT_INCLUDE_INFO=true
33
+ EXPORT_INCLUDE_TIMESTAMP=true
34
+ EXPORT_INCLUDE_USER_INFO=true
35
+ EXPORT_INCLUDE_COMPANY_INFO=true
36
+ ```
37
+
38
+ ### Config File
39
+ File konfigurasi tersedia di `config/export_info.php` dengan pengaturan untuk:
40
+ - Author information
41
+ - Company details
42
+ - Export settings
43
+ - Default styles
44
+ - Format configurations
45
+
46
+ ## Basic Usage
47
+
48
+ ### 1. Simple Table Export
49
+
50
+ ```php
51
+ use App\Exports\SimpleTableExport;
52
+ use App\Models\User;
53
+
54
+ // Basic export
55
+ $query = User::query();
56
+ $headers = ['ID', 'Name', 'Email', 'Created At'];
57
+
58
+ $export = SimpleTableExport::make($query, $headers, 'Users', 'Users Report');
59
+
60
+ // Download file
61
+ return $export->download();
62
+
63
+ // Or save to file
64
+ $filePath = $export->toFile();
65
+ ```
66
+
67
+ ### 2. Custom Column Mapping
68
+
69
+ ```php
70
+ $headers = ['ID', 'Full Name', 'Email', 'Status', 'Join Date'];
71
+ $columnMappings = [
72
+ 'id',
73
+ 'name',
74
+ 'email',
75
+ function ($user) {
76
+ return $user->email_verified_at ? 'Verified' : 'Unverified';
77
+ },
78
+ function ($user) {
79
+ return $user->created_at->format('d/m/Y');
80
+ }
81
+ ];
82
+
83
+ $export = SimpleTableExport::make($query, $headers, 'Users')
84
+ ->setColumnMappings($columnMappings)
85
+ ->setReportTitle('User Status Report');
86
+
87
+ return $export->download();
88
+ ```
89
+
90
+ ### 3. Multiple Sheets Export
91
+
92
+ ```php
93
+ use App\Exports\UsersPostsExport;
94
+ use App\Models\User;
95
+ use App\Models\Post;
96
+
97
+ // Create export with multiple sheets
98
+ $userQuery = User::whereDate('created_at', '>=', '2024-01-01');
99
+ $postQuery = Post::whereDate('created_at', '>=', '2024-01-01');
100
+
101
+ $export = new UsersPostsExport($userQuery, $postQuery);
102
+ $export->setReportTitle('Q1 2024 Data Report');
103
+
104
+ return $export->download();
105
+ ```
106
+
107
+ ## Advanced Usage
108
+
109
+ ### 1. Using ExcelExportService Directly
110
+
111
+ ```php
112
+ use App\Services\ExcelExportService;
113
+ use App\Models\User;
114
+
115
+ $exportService = new ExcelExportService();
116
+
117
+ // Create multiple sheets
118
+ $exportService
119
+ ->createSheet('Users', true)
120
+ ->createSheet('Summary');
121
+
122
+ // Add data to Users sheet
123
+ $exportService
124
+ ->addExportInfo('Users', 'User Data Report')
125
+ ->addHeaders('Users', ['ID', 'Name', 'Email', 'Created At'])
126
+ ->addData('Users', User::select(['id', 'name', 'email', 'created_at']))
127
+ ->autoSizeColumns('Users')
128
+ ->freezePane('Users', 'A2');
129
+
130
+ // Add summary to Summary sheet
131
+ $summaryData = [
132
+ [
133
+ 'title' => 'User Statistics',
134
+ 'headers' => ['Metric', 'Value'],
135
+ 'data' => [
136
+ ['Total Users', User::count()],
137
+ ['Active Users', User::whereNotNull('email_verified_at')->count()],
138
+ ['New Users This Month', User::whereMonth('created_at', now()->month)->count()],
139
+ ]
140
+ ]
141
+ ];
142
+
143
+ $exportService
144
+ ->addExportInfo('Summary', 'Data Summary')
145
+ ->addMultipleTables('Summary', $summaryData)
146
+ ->autoSizeColumns('Summary');
147
+
148
+ // Export
149
+ $filename = 'user_report_' . now()->format('Y-m-d_H-i-s') . '.xlsx';
150
+ return $exportService->download($filename);
151
+ ```
152
+
153
+ ### 2. Custom Styling
154
+
155
+ ```php
156
+ // Define custom styles
157
+ $customHeaderStyle = [
158
+ 'font' => [
159
+ 'bold' => true,
160
+ 'size' => 14,
161
+ 'color' => ['rgb' => 'FFFFFF'],
162
+ ],
163
+ 'fill' => [
164
+ 'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
165
+ 'startColor' => ['rgb' => '4CAF50'],
166
+ ],
167
+ 'borders' => [
168
+ 'allBorders' => [
169
+ 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THICK,
170
+ 'color' => ['rgb' => '000000'],
171
+ ],
172
+ ],
173
+ ];
174
+
175
+ $customBodyStyle = [
176
+ 'font' => ['size' => 11],
177
+ 'borders' => [
178
+ 'allBorders' => [
179
+ 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
180
+ 'color' => ['rgb' => 'DDDDDD'],
181
+ ],
182
+ ],
183
+ ];
184
+
185
+ // Apply to SimpleTableExport
186
+ $export = SimpleTableExport::make($query, $headers, 'Custom Report')
187
+ ->setCustomStyles($customBodyStyle);
188
+
189
+ // Or apply directly to service
190
+ $exportService
191
+ ->addHeaders('Sheet1', $headers)
192
+ ->applyStyle($worksheet, 'A1:D1', $customHeaderStyle)
193
+ ->addData('Sheet1', $data, 1, $customBodyStyle);
194
+ ```
195
+
196
+ ### 3. Column Width and Formatting
197
+
198
+ ```php
199
+ $export = SimpleTableExport::make($query, $headers, 'Formatted Report')
200
+ ->setColumnWidths([
201
+ 'A' => 20, // ID column
202
+ 'B' => 30, // Name column
203
+ 'C' => 35, // Email column
204
+ 'D' => 25 // Date column
205
+ ]);
206
+
207
+ // Or use auto-size (default behavior)
208
+ $export->autoSizeColumns('Sheet1');
209
+ ```
210
+
211
+ ## API Endpoints
212
+
213
+ ### Available Endpoints
214
+
215
+ ```
216
+ GET /api/v1/export/users-posts // Export users and posts
217
+ GET /api/v1/export/users // Export users only
218
+ GET /api/v1/export/custom-styled // Custom styled example
219
+ GET /api/v1/export/multiple-tables // Multiple tables example
220
+ ```
221
+
222
+ ### Query Parameters
223
+
224
+ - `download=true/false` - Download file or return file path (default: true)
225
+ - `date_from` - Filter data from date (YYYY-MM-DD)
226
+ - `date_to` - Filter data to date (YYYY-MM-DD)
227
+ - `search` - Search term for filtering
228
+ - `verified=true/false` - Filter verified/unverified users
229
+
230
+ ### Example API Calls
231
+
232
+ ```bash
233
+ # Download users and posts export
234
+ curl -H "Authorization: Bearer {token}" \
235
+ "http://localhost:8000/api/v1/export/users-posts?download=true"
236
+
237
+ # Get file path for users export with date filter
238
+ curl -H "Authorization: Bearer {token}" \
239
+ "http://localhost:8000/api/v1/export/users?download=false&date_from=2024-01-01&date_to=2024-12-31"
240
+
241
+ # Export verified users only
242
+ curl -H "Authorization: Bearer {token}" \
243
+ "http://localhost:8000/api/v1/export/users?verified=true&search=john"
244
+ ```
245
+
246
+ ## Creating Custom Export Classes
247
+
248
+ ### 1. Extend BaseExport
249
+
250
+ ```php
251
+ <?php
252
+
253
+ namespace App\Exports;
254
+
255
+ class CustomExport extends BaseExport
256
+ {
257
+ protected $data;
258
+ protected $options;
259
+
260
+ public function __construct($data, array $options = [])
261
+ {
262
+ parent::__construct();
263
+
264
+ $this->data = $data;
265
+ $this->options = $options;
266
+ $this->reportTitle = $options['title'] ?? 'Custom Report';
267
+ }
268
+
269
+ public function export()
270
+ {
271
+ $this->exportService
272
+ ->createSheet('Data', true)
273
+ ->addExportInfo('Data', $this->reportTitle);
274
+
275
+ // Your custom logic here
276
+ $headers = $this->options['headers'] ?? ['Column 1', 'Column 2'];
277
+
278
+ $this->exportService
279
+ ->addHeaders('Data', $headers)
280
+ ->addData('Data', $this->data)
281
+ ->autoSizeColumns('Data')
282
+ ->freezePane('Data', 'A2');
283
+ }
284
+ }
285
+ ```
286
+
287
+ ### 2. Use the Custom Export
288
+
289
+ ```php
290
+ $data = collect([
291
+ ['Value 1', 'Value 2'],
292
+ ['Value 3', 'Value 4'],
293
+ ]);
294
+
295
+ $export = new CustomExport($data, [
296
+ 'title' => 'My Custom Report',
297
+ 'headers' => ['Column A', 'Column B']
298
+ ]);
299
+
300
+ return $export->download();
301
+ ```
302
+
303
+ ## Performance Tips
304
+
305
+ 1. **Use Chunking**: Service automatically chunks data per 1000 records
306
+ 2. **Memory Limit**: Adjust `EXPORT_MEMORY_LIMIT` in .env for large datasets
307
+ 3. **Execution Time**: Set `EXPORT_MAX_EXECUTION_TIME` appropriately
308
+ 4. **Selective Fields**: Only select required columns from database
309
+
310
+ ```php
311
+ // Good - select specific columns
312
+ $query = User::select(['id', 'name', 'email', 'created_at']);
313
+
314
+ // Avoid - select all columns
315
+ $query = User::all();
316
+ ```
317
+
318
+ ## Error Handling
319
+
320
+ Service includes built-in error handling. Wrap calls in try-catch for custom error handling:
321
+
322
+ ```php
323
+ try {
324
+ $export = new UsersPostsExport();
325
+ return $export->download();
326
+ } catch (\Exception $e) {
327
+ return response()->json([
328
+ 'error' => 'Export failed: ' . $e->getMessage()
329
+ ], 500);
330
+ }
331
+ ```
332
+
333
+ ## Troubleshooting
334
+
335
+ ### Common Issues
336
+
337
+ 1. **Memory Limit Exceeded**: Increase `EXPORT_MEMORY_LIMIT`
338
+ 2. **Execution Timeout**: Increase `EXPORT_MAX_EXECUTION_TIME`
339
+ 3. **File Not Found**: Check `EXPORT_TEMP_DIRECTORY` permissions
340
+ 4. **Style Not Applied**: Verify PhpSpreadsheet style array format
341
+
342
+ ### Debug Mode
343
+
344
+ Enable debug logging:
345
+
346
+ ```php
347
+ // In export class
348
+ \Log::info('Export started', ['query_count' => $query->count()]);
349
+ ```
@@ -0,0 +1,340 @@
1
+ # Export Data Providers Documentation
2
+
3
+ ## Overview
4
+ Data Providers adalah komponen yang memisahkan logika data (rawData, headers, dataMapper) dari controller. Ini membuat code lebih modular, testable, dan mudah di-maintain.
5
+
6
+ ## Structure
7
+ ```
8
+ app/Exports/DataProviders/
9
+ ├── ExportDataProviderInterface.php (Interface)
10
+ ├── FlexibleTemplateDataProvider.php
11
+ ├── MultiSheetTemplateDataProvider.php
12
+ ├── MultiTableTemplateDataProvider.php
13
+ ├── UserExportDataProvider.php
14
+ ├── ExternalDataProvider.php
15
+ └── ProductExportDataProvider.php
16
+ ```
17
+
18
+ ## Interface Contract
19
+ Setiap Data Provider harus implement `ExportDataProviderInterface`:
20
+
21
+ ```php
22
+ interface ExportDataProviderInterface
23
+ {
24
+ public function getRawData($filters = null): array;
25
+ public function getHeaders(): array;
26
+ public function getDataMapper(): array;
27
+ public function getOptions(): array;
28
+ }
29
+ ```
30
+
31
+ ## Usage in Controller
32
+
33
+ ### Before (Dirty Controller)
34
+ ```php
35
+ public function exportFlexibleTemplate(Request $request)
36
+ {
37
+ // 50+ lines of hard-coded data, headers, mappers
38
+ $rawData = [/* lots of data */];
39
+ $headers = [/* headers */];
40
+ $dataMapper = [/* mappers */];
41
+ // ...
42
+ }
43
+ ```
44
+
45
+ ### After (Clean Controller)
46
+ ```php
47
+ public function exportFlexibleTemplate(Request $request)
48
+ {
49
+ $provider = new FlexibleTemplateDataProvider();
50
+
51
+ $rawData = $provider->getRawData();
52
+ $headers = $provider->getHeaders();
53
+ $dataMapper = $provider->getDataMapper();
54
+ $options = $provider->getOptions();
55
+
56
+ $export = FlexibleExport::create($rawData, $headers, array_merge($options, [
57
+ 'data_mapper' => $dataMapper
58
+ ]));
59
+
60
+ return $request->boolean('download', true) ? $export->download() : /* JSON response */;
61
+ }
62
+ ```
63
+
64
+ ## Benefits
65
+
66
+ ### 1. Separation of Concerns
67
+ - Controller hanya handle HTTP layer
68
+ - Data Provider handle data preparation
69
+ - Export Templates handle Excel generation
70
+
71
+ ### 2. Reusability
72
+ Data providers bisa digunakan di berbagai controller atau command:
73
+ ```php
74
+ // Di Controller
75
+ $provider = new UserExportDataProvider($request);
76
+
77
+ // Di Artisan Command
78
+ $provider = new UserExportDataProvider();
79
+
80
+ // Di Job Queue
81
+ $provider = new UserExportDataProvider();
82
+ ```
83
+
84
+ ### 3. Testability
85
+ ```php
86
+ class UserExportDataProviderTest extends TestCase
87
+ {
88
+ public function test_get_headers()
89
+ {
90
+ $provider = new UserExportDataProvider(new Request());
91
+ $headers = $provider->getHeaders();
92
+
93
+ $this->assertEquals(['ID', 'Full Name', 'Email Address', ...], $headers);
94
+ }
95
+ }
96
+ ```
97
+
98
+ ### 4. Maintainability
99
+ Ubah data mapping tanpa touch controller:
100
+ ```php
101
+ // UserExportDataProvider.php
102
+ public function getDataMapper(): array
103
+ {
104
+ return [
105
+ 'id',
106
+ 'name',
107
+ 'email',
108
+ // Add new formatter without changing controller
109
+ function ($user) {
110
+ return $user['premium'] ? 'Premium ⭐' : 'Regular';
111
+ }
112
+ ];
113
+ }
114
+ ```
115
+
116
+ ## Provider Types
117
+
118
+ ### 1. Simple Data Provider
119
+ Untuk static/sample data:
120
+ ```php
121
+ class FlexibleTemplateDataProvider implements ExportDataProviderInterface
122
+ {
123
+ public function getRawData($filters = null): array
124
+ {
125
+ return [/* static sample data */];
126
+ }
127
+ }
128
+ ```
129
+
130
+ ### 2. Model-based Data Provider
131
+ Untuk data dari database:
132
+ ```php
133
+ class UserExportDataProvider implements ExportDataProviderInterface
134
+ {
135
+ private Request $request;
136
+
137
+ public function __construct(Request $request)
138
+ {
139
+ $this->request = $request;
140
+ }
141
+
142
+ public function getRawData($filters = null): array
143
+ {
144
+ $query = User::query();
145
+ // Apply request filters
146
+ return $query->get()->toArray();
147
+ }
148
+ }
149
+ ```
150
+
151
+ ### 3. Complex Data Provider
152
+ Untuk multi-sheet/multi-table:
153
+ ```php
154
+ class MultiSheetTemplateDataProvider implements ExportDataProviderInterface
155
+ {
156
+ // Implement helper methods
157
+ public function getFormattedSheets(): array
158
+ {
159
+ // Return ready-to-use sheets configuration
160
+ }
161
+ }
162
+ ```
163
+
164
+ ### 4. External API Data Provider
165
+ Untuk data dari API external:
166
+ ```php
167
+ class ExternalDataProvider implements ExportDataProviderInterface
168
+ {
169
+ public function getRawData($filters = null): array
170
+ {
171
+ // Fetch from external API
172
+ // Transform data
173
+ return $transformedData;
174
+ }
175
+ }
176
+ ```
177
+
178
+ ## Creating New Data Provider
179
+
180
+ ### Step 1: Create Provider Class
181
+ ```php
182
+ <?php
183
+ namespace App\Exports\DataProviders;
184
+
185
+ class NewExportDataProvider implements ExportDataProviderInterface
186
+ {
187
+ public function getRawData($filters = null): array
188
+ {
189
+ // Your data logic here
190
+ return [];
191
+ }
192
+
193
+ public function getHeaders(): array
194
+ {
195
+ return ['Column 1', 'Column 2'];
196
+ }
197
+
198
+ public function getDataMapper(): array
199
+ {
200
+ return [
201
+ 'field1',
202
+ function ($item) {
203
+ return formatValue($item['field2']);
204
+ }
205
+ ];
206
+ }
207
+
208
+ public function getOptions(): array
209
+ {
210
+ return [
211
+ 'sheet_title' => 'My Export',
212
+ 'report_title' => 'My Report',
213
+ 'column_widths' => ['A' => 15, 'B' => 20],
214
+ 'freeze_pane' => 'A2'
215
+ ];
216
+ }
217
+ }
218
+ ```
219
+
220
+ ### Step 2: Use in Controller
221
+ ```php
222
+ public function exportNewTemplate(Request $request)
223
+ {
224
+ try {
225
+ $provider = new NewExportDataProvider();
226
+
227
+ $rawData = $provider->getRawData();
228
+ $headers = $provider->getHeaders();
229
+ $dataMapper = $provider->getDataMapper();
230
+ $options = $provider->getOptions();
231
+
232
+ $export = FlexibleExport::create($rawData, $headers, array_merge($options, [
233
+ 'data_mapper' => $dataMapper
234
+ ]));
235
+
236
+ return $request->boolean('download', true) ? $export->download() : /* JSON response */;
237
+
238
+ } catch (\Exception $e) {
239
+ return response()->json([
240
+ 'success' => false,
241
+ 'message' => 'Export failed: ' . $e->getMessage()
242
+ ], 500);
243
+ }
244
+ }
245
+ ```
246
+
247
+ ## Advanced Features
248
+
249
+ ### Dynamic Filtering
250
+ ```php
251
+ public function getRawData($filters = null): array
252
+ {
253
+ $query = Model::query();
254
+
255
+ if ($filters) {
256
+ foreach ($filters as $key => $value) {
257
+ $query->where($key, $value);
258
+ }
259
+ }
260
+
261
+ return $query->get()->toArray();
262
+ }
263
+ ```
264
+
265
+ ### Conditional Data Mapping
266
+ ```php
267
+ public function getDataMapper(): array
268
+ {
269
+ $mappers = ['id', 'name', 'email'];
270
+
271
+ // Add conditional mappers
272
+ if (auth()->user()->hasPermission('view_sensitive_data')) {
273
+ $mappers[] = function ($item) {
274
+ return $item['social_security_number'];
275
+ };
276
+ }
277
+
278
+ return $mappers;
279
+ }
280
+ ```
281
+
282
+ ### Caching Support
283
+ ```php
284
+ public function getRawData($filters = null): array
285
+ {
286
+ $cacheKey = 'export_data_' . md5(serialize($filters));
287
+
288
+ return Cache::remember($cacheKey, 300, function () use ($filters) {
289
+ return Model::query()->where($filters)->get()->toArray();
290
+ });
291
+ }
292
+ ```
293
+
294
+ ## Testing Examples
295
+
296
+ ```php
297
+ class UserExportDataProviderTest extends TestCase
298
+ {
299
+ public function test_headers_contain_required_columns()
300
+ {
301
+ $provider = new UserExportDataProvider(new Request());
302
+ $headers = $provider->getHeaders();
303
+
304
+ $this->assertContains('ID', $headers);
305
+ $this->assertContains('Full Name', $headers);
306
+ $this->assertContains('Email Address', $headers);
307
+ }
308
+
309
+ public function test_data_mapper_formats_correctly()
310
+ {
311
+ $provider = new UserExportDataProvider(new Request());
312
+ $mapper = $provider->getDataMapper();
313
+
314
+ $testData = ['email_verified_at' => '2024-01-15'];
315
+ $result = $mapper[3]($testData); // Verification status mapper
316
+
317
+ $this->assertEquals('Verified ✓', $result);
318
+ }
319
+ }
320
+ ```
321
+
322
+ ## Best Practices
323
+
324
+ 1. **Single Responsibility**: Satu provider untuk satu jenis export
325
+ 2. **Consistent Naming**: `[Entity]ExportDataProvider` atau `[Purpose]DataProvider`
326
+ 3. **Documentation**: Comment complex data mappers
327
+ 4. **Error Handling**: Handle missing/invalid data gracefully
328
+ 5. **Performance**: Use eager loading, chunking untuk data besar
329
+ 6. **Security**: Validate permissions dalam getRawData()
330
+
331
+ ## Migration Path
332
+
333
+ 1. Identify hard-coded data in controllers
334
+ 2. Create corresponding data provider
335
+ 3. Move data logic to provider
336
+ 4. Update controller to use provider
337
+ 5. Test functionality
338
+ 6. Remove old hard-coded data
339
+
340
+ Semua export functions telah berhasil di-refactor dan tested! 🎉