Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
5fd2008
Making export possible refs #85
nielsdrost7 Sep 7, 2025
4e0333e
Some more Export tests refs #85
nielsdrost7 Sep 7, 2025
f130658
Making export possible refs #85
nielsdrost7 Sep 7, 2025
80e30bc
Adds the maatwebsite/excel package and prepares all exports, export s…
nielsdrost7 Sep 7, 2025
bb19f7b
Intermediary commits for the exports refs #85
nielsdrost7 Sep 7, 2025
9389692
Intermediary commits for the exports refs #85
nielsdrost7 Sep 7, 2025
47363f0
Intermediary commits for the exports refs #85
nielsdrost7 Sep 7, 2025
9cb77a2
Exports for Projects, Tasks, Products, Payments, Invoices, Quotes, Ex…
nielsdrost7 Sep 7, 2025
051b314
Exports for Projects, Tasks, Products, Payments, Invoices, Quotes, Ex…
nielsdrost7 Sep 8, 2025
a2717a0
just a new phpstan baseline (8 more errors)
nielsdrost7 Sep 8, 2025
cd94212
Merge branch 'develop' of github.com:InvoicePlane/InvoicePlane-v2 int…
nielsdrost7 Oct 27, 2025
b580f39
Update Modules/Clients/Exports/ContactsExport.php
nielsdrost7 Nov 13, 2025
2d32950
Update Modules/Clients/Exports/ContactsLegacyExport.php
nielsdrost7 Nov 13, 2025
8e692a9
Update Modules/Quotes/Feature/Modules/QuotesExportImportTest.php
nielsdrost7 Nov 13, 2025
dd40abe
Update Modules/Expenses/Exports/ExpensesExport.php
nielsdrost7 Nov 13, 2025
2ec66cc
Update Modules/Payments/Services/PaymentExportService.php
nielsdrost7 Nov 13, 2025
d76de23
Refactor exports to use Filament Export Actions with SOLID/DRY princi…
Copilot Nov 13, 2025
5e9cfe9
Refactor export tests, document queue requirements, and add AI agent …
Copilot Nov 13, 2025
1ecd5a5
Update Modules/Projects/Services/ProjectExportService.php
nielsdrost7 Nov 13, 2025
9defe4b
Add automated production release workflow with Crowdin integration, a…
Copilot Nov 21, 2025
d8ab784
Apply suggestions from code review
nielsdrost7 Nov 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
239 changes: 239 additions & 0 deletions .github/EXPORT-REFACTORING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
# Export Refactoring - Filament Export Action

## Overview

This document outlines the refactoring of export functionality from Maatwebsite/Excel to Filament's built-in Export Action system.

## Changes Made

### 1. Created Filament Exporters

All modules now have dedicated Filament Exporters located in `Modules/{ModuleName}/Filament/Exporters/`:

**Architecture Improvements:**
- All exporters extend `Modules/Core/Filament/Exporters/BaseExporter` (follows SOLID/DRY principles)
- BaseExporter provides centralized, translatable notification logic
- Each exporter implements abstract `getEntityName()` for dynamic entity naming
- Eliminates code duplication across 18 exporter classes

**Proper Type Handling:**
- Enum values: Use `->formatStateUsing(fn ($state) => $state?->label() ?? '')` to call label() method
- Date fields: Use `->date()` method for proper date formatting
- Accessor attributes: Explicitly handle with `->formatStateUsing(fn ($state, $record) => $record->accessor_name)`

**Internationalization:**
- All notification strings use trans() function
- New translation keys in resources/lang/en/ip.php:
- `export_completed` - Success notification
- `export_failed_rows` - Failure notification
- `row` - Pluralizable row/rows

**Expenses Module:**
- `ExpenseExporter` - Regular export with 7 columns
- `ExpenseLegacyExporter` - Legacy export with 3 columns

**Products Module:**
- `ProductExporter` - Regular export with 7 columns
- `ProductLegacyExporter` - Legacy export with 3 columns

**Quotes Module:**
- `QuoteExporter` - Regular export with 8 columns
- `QuoteLegacyExporter` - Legacy export with 6 columns

**Projects Module:**
- `ProjectExporter` - Regular export with 5 columns
- `ProjectLegacyExporter` - Legacy export with 5 columns

**Tasks (Projects Module):**
- `TaskExporter` - Regular export with 6 columns
- `TaskLegacyExporter` - Legacy export with 6 columns

**Clients Module (Relations):**
- `RelationExporter` - Regular export with 11 columns
- `RelationLegacyExporter` - Legacy export with 4 columns

**Clients Module (Contacts):**
- `ContactExporter` - Regular export with 6 columns
- `ContactLegacyExporter` - Legacy export with 6 columns

**Invoices Module:**
- `InvoiceExporter` - Regular export with 6 columns
- `InvoiceLegacyExporter` - Legacy export with 4 columns

**Payments Module:**
- `PaymentExporter` - Regular export with 5 columns
- `PaymentLegacyExporter` - Legacy export with 4 columns

### 2. Updated List Pages

The following List Pages were updated to use Filament `ExportAction` instead of custom export services:

- `Modules/Expenses/Filament/Company/Resources/Expenses/Pages/ListExpenses.php`
- `Modules/Products/Filament/Company/Resources/Products/Pages/ListProducts.php`
- `Modules/Quotes/Filament/Company/Resources/Quotes/Pages/ListQuotes.php`
- `Modules/Projects/Filament/Company/Resources/Projects/Pages/ListProjects.php`
- `Modules/Projects/Filament/Company/Resources/Tasks/Pages/ListTasks.php`
- `Modules/Clients/Filament/Company/Resources/Relations/Pages/ListRelations.php`
- `Modules/Clients/Filament/Company/Resources/Contacts/Pages/ListContacts.php`
- `Modules/Invoices/Filament/Company/Resources/Invoices/Pages/ListInvoices.php`
- `Modules/Payments/Filament/Company/Resources/Payments/Pages/ListPayments.php`

### 3. Export Actions Available

Each List Page now has 4 export actions in an action group:

1. **Export as CSV (v2)** - Uses the regular exporter with CSV format
2. **Export as CSV (v1, Legacy)** - Uses the legacy exporter with CSV format
3. **Export as Excel (v2)** - Uses the regular exporter with XLSX format
4. **Export as Excel (v1, Legacy)** - Uses the legacy exporter with XLSX format

### 4. Database Migration

A new migration was added to create the `exports` table required by Filament Export:

- `Modules/Core/Database/Migrations/2025_11_13_061624_create_exports_table.php`

Run migrations to apply:
```bash
php artisan migrate
```

## Backward Compatibility

### Preserved Components

The following components are preserved for backward compatibility:

1. **All Maatwebsite/Excel Export Classes** (kept in `Modules/{ModuleName}/Exports/`)
2. **All Export Services** (kept in `Modules/{ModuleName}/Services/`)

These can be deprecated in a future release once the Filament Export system is fully tested and adopted.

## How Filament Export Works

### User Experience

1. User clicks on an export action
2. A modal opens showing available columns to export
3. User can select/deselect columns and customize column labels
4. User clicks "Export"
5. Export job is queued and runs asynchronously
6. User receives a notification when export is complete
7. User can download the exported file from the notification

### Technical Flow

1. `ExportAction` creates an `Export` database record
2. Export jobs are dispatched to the queue
3. Jobs process records in chunks (default: 100 rows per chunk)
4. Progress is tracked in the `exports` table
5. On completion, a notification is sent to the user
6. Exported file is stored on configured disk

### Configuration

Exporters can be configured in each `*Exporter.php` class:

- `getColumns()` - Define exportable columns
- `getModel()` - Specify the model being exported
- `getCompletedNotificationBody()` - Customize completion notification
- `getOptionsFormComponents()` - Add custom export options

## Testing

### Manual Testing Steps

For each module (Expenses, Products, Quotes, Projects, Tasks, Relations, Contacts, Invoices, Payments):

1. Navigate to the list page
2. Click the "Export" button
3. Test each of the 4 export options:
- Export as CSV (v2)
- Export as CSV (v1, Legacy)
- Export as Excel (v2)
- Export as Excel (v1, Legacy)
4. Verify:
- Modal opens with column selection
- Export completes successfully
- Notification is received
- File downloads correctly
- File contains expected data and columns

### Automated Testing

**Note:** Filament Export requires comprehensive test rewrite, not simple updates.

The existing test files are marked as incomplete and need complete rewriting to test Filament Export's asynchronous behavior:

- `Modules/Expenses/Feature/Modules/ExpensesExportImportTest.php`
- `Modules/Products/Feature/Modules/ProductsExportImportTest.php`
- `Modules/Quotes/Feature/Modules/QuotesExportImportTest.php`
- `Modules/Projects/Feature/Modules/ProjectsExportImportTest.php`
- `Modules/Projects/Feature/Modules/TasksExportImportTest.php`

**Why tests need complete rewrite:**

Filament Export fundamentally changes the export flow from synchronous to asynchronous:

**Old Flow (Maatwebsite/Excel):**
1. User clicks export button
2. Export executes immediately
3. File downloads directly
4. Test: Call action, check response

**New Flow (Filament Export):**
1. User clicks export button
2. Modal opens for column selection
3. User submits form
4. Export job queued
5. Jobs process asynchronously
6. Notification sent on completion
7. User downloads from notification

**Test Requirements:**
- Mock/fake queue system
- Test Livewire modal interactions
- Verify job dispatching
- Check database records in exports table
- Validate notification delivery
- Test file generation and storage
- Verify column selection functionality

This is a significant undertaking beyond the scope of export refactoring. Tests are documented for future implementation.

## Future Improvements

1. **Deprecate Export Services**: Once Filament Export is fully tested, the old export services can be removed
2. **Update Tests**: Rewrite export tests to work with Filament's asynchronous export system
3. **Custom Export Options**: Add filtering, date ranges, and other export options via `getOptionsFormComponents()`
4. **Scheduled Exports**: Implement recurring exports using Filament's export scheduling features
5. **Export Templates**: Allow users to save preferred export configurations

## Troubleshooting

### Queue Configuration

Filament Export uses Laravel's queue system. Ensure your queue is configured:

```bash
# Start queue worker
php artisan queue:work
```

### Storage Configuration

Exports are stored using Laravel's filesystem. Ensure your storage is configured in `config/filesystems.php`.

### Permission Issues

Ensure the `exports` table exists and migrations have been run:

```bash
php artisan migrate
```

## References

- [Filament Export Documentation](https://filamentphp.com/docs/4.x/actions/export)
- [Laravel Queue Documentation](https://laravel.com/docs/queues)
- [Maatwebsite/Excel Documentation](https://docs.laravel-excel.com)
18 changes: 18 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ This project is **InvoicePlane v2**, a **multi-tenant Laravel application** with
- **Module System:** nwidart/laravel-modules
- **Permissions:** spatie/laravel-permission
- **Multi-tenancy:** Filament Companies with `BelongsToCompany` trait
- **Queue System:** Required for export functionality (Redis, database, or sync for local development)

## Development Commands

Expand Down Expand Up @@ -57,8 +58,16 @@ composer install
cp .env.example .env
php artisan key:generate
php artisan migrate --seed

# Start queue worker for export functionality
php artisan queue:work
```

**Queue Configuration:**
- Export functionality requires a queue worker to be running
- For local development, you can use `QUEUE_CONNECTION=sync` in `.env`
- For production, use Redis or database queue driver with Supervisor

## Related Documentation

- **Installation:** `.github/INSTALLATION.md`
Expand Down Expand Up @@ -124,6 +133,15 @@ php artisan migrate --seed
- Reusable logic (e.g., fixtures, setup) must live in abstract test cases, not inline.
- Tests have inline comment blocks above sections (Arrange, Act, Assert).

### Export System Rules

- **Exports use Filament's asynchronous export system** which requires queue workers.
- **Export tests must use fakes:** `Queue::fake()`, `Storage::fake()`, and verify job dispatching with `Bus::assertChained()`.
- **The `exports` table is temporary** and managed by Filament for job coordination only.
- **No export history feature** - export records are ephemeral and auto-prunable.
- **Queue configuration is required** for export functionality to work in production.
- See `Modules/Core/Filament/Exporters/README.md` for export architecture details.

### Database & Models

- **No `$fillable` array in Models.**
Expand Down
Loading