Skip to content

Fix Filament action imports, grid calculations, and refactor test mocks to fakes in Report Builder#351

Merged
nielsdrost7 merged 4 commits into
feature/98-report-builder-onlyfrom
copilot/sub-pr-349
Jan 9, 2026
Merged

Fix Filament action imports, grid calculations, and refactor test mocks to fakes in Report Builder#351
nielsdrost7 merged 4 commits into
feature/98-report-builder-onlyfrom
copilot/sub-pr-349

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Jan 9, 2026

Addresses feedback from #349 review: incorrect Filament action namespace usage, grid snapping calculation bug, test mock method mismatch, and Tailwind v4 syntax migration. Additionally refactors tests to use Storage fakes instead of mocks per project guidelines.

Changes

ReportBlocksTable.php

  • Import actions from Filament\Tables\Actions\* instead of Filament\Actions\* (page-level vs table-level)
  • Replace ->recordActions() with ->actions() for correct table API
  • Remove unused array $data parameter from DeleteAction closure

GridSnapperService.php

  • Use clamped $x in width calculation instead of unclamped $position->getX()
  • Prevents width overflow when position is snapped to grid boundary
// Before: used original X, could exceed grid
$width = max(1, min($position->getWidth(), $this->gridSize - $position->getX()));

// After: uses clamped X
$width = max(1, min($position->getWidth(), $this->gridSize - $x));

ReportTemplateServiceTest.php

  • Refactored from mocks to Storage::fake('report_templates') following project guideline "Prefer Fakes and Fixtures over Mocks"
  • Use real ReportTemplateFileRepository instance with faked storage layer
  • it_persists_blocks() now validates actual file creation and content using Storage assertions
  • it_loads_blocks() now creates test fixtures using Storage::put() instead of mocking return values
  • Provides better integration test coverage by testing real repository logic

invoiceplane.css

  • Migrate Tailwind v4 important modifier: !bg-primary-700bg-primary-700!

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 9, 2026

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Comment @coderabbitai help to get the list of available commands and usage tips.

…, and CSS syntax

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>
Copilot AI changed the title [WIP] Update action corrections and test updates for report builder Fix Filament action imports, grid calculations, and test mocks in Report Builder Jan 9, 2026
Copilot AI requested a review from nielsdrost7 January 9, 2026 03:22
Copy link
Copy Markdown
Collaborator

@nielsdrost7 nielsdrost7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot I prefer faking over mocking.
Any changes required?

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Jan 9, 2026

@copilot I prefer faking over mocking.
Any changes required?

No changes required - the code now uses Storage::fake('report_templates') instead of mocking the repository, following the project guideline "Prefer Fakes and Fixtures over Mocks".

Changes in commit eaa747f:

  • Replaced $this->createMock(ReportTemplateFileRepository::class) with new ReportTemplateFileRepository()
  • Added Storage::fake('report_templates') in setUp()
  • it_persists_blocks() now uses Storage::disk('report_templates')->assertExists() and validates actual file content
  • it_loads_blocks() now uses Storage::disk('report_templates')->put() to create test data instead of mocking get()

Both tests now interact with the real repository using Laravel's Storage fake, providing better integration test coverage.

Copilot AI changed the title Fix Filament action imports, grid calculations, and test mocks in Report Builder Fix Filament action imports, grid calculations, and refactor test mocks to fakes in Report Builder Jan 9, 2026
Copilot AI requested a review from nielsdrost7 January 9, 2026 03:47
@nielsdrost7 nielsdrost7 marked this pull request as ready for review January 9, 2026 04:05
@nielsdrost7 nielsdrost7 merged commit 4bf32e2 into feature/98-report-builder-only Jan 9, 2026
1 check passed
@nielsdrost7 nielsdrost7 deleted the copilot/sub-pr-349 branch January 9, 2026 04:05
nielsdrost7 added a commit that referenced this pull request May 25, 2026
* Branch Report Builder initial

* Removed Invoices temporarily

* 126: Peppo;l

* temporary-total

* temp

* Delete Modules/ReportBuilder directory

* Composer correct

* Composer correct

* Update pint.yml

* Fix Filament action imports, grid calculations, and refactor test mocks to fakes in Report Builder (#351)

* Initial plan

* Fix ReportBlocksTable imports, actions, GridSnapperService, test mock, and CSS syntax

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Refactor tests to use Storage::fake() instead of mocking repository

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Change actions to recordActions in ReportBlocksTable

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* merged in develop branch

* Add comprehensive Mason package integration plan

- Document installation steps and theme setup
- Detail architecture changes from custom to Mason
- Provide code examples for all Brick classes
- Include Blade view templates for preview/render
- Add BricksCollection structure
- Describe storage adapter pattern for JSON persistence
- List all translation keys needed
- Outline testing strategy with Mason Faker
- Include phased migration approach

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Update Mason refactor plan with status and next steps

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Implement Mason package integration for ReportBuilder

- Create 6 Mason Brick classes (HeaderCompany, HeaderClient, HeaderInvoiceMeta, DetailItems, FooterTotals, FooterNotes)
- Create ReportBricksCollection to organize bricks by section
- Add preview and render Blade templates for all bricks
- Implement MasonStorageAdapter to convert between Mason JSON and BlockDTO
- Create mason-preview layout for WYSIWYG editing experience
- Add 60+ translation keys for Mason UI elements
- Maintain filesystem JSON storage (no database changes)

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Wire Mason into ReportBuilder and add comprehensive tests

- Update ReportBuilder.php to support Mason field with MasonStorageAdapter
- Add masonContent property and loadMasonContent() method
- Implement saveMasonContent() for Mason-based saves with legacy fallback
- Add getMasonEditorSchema() for Filament Mason field configuration
- Fix syntax error in FooterTotalsBrick (wrong operator)
- Create MasonStorageAdapterTest with 10 test cases for conversion logic
- Create MasonBricksTest with 16 tests for all 6 brick classes
- Create ReportBricksCollectionTest with 7 tests for collection methods
- Create ReportBuilderMasonIntegrationTest with 8 integration tests
- All tests validate roundtrip conversion, config preservation, and multi-brick handling

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Add 5 new Mason bricks and simplify storage (remove BlockDTO)

- Create HeaderProjectBrick with project_number, project_name, dates, status fields
- Create HeaderQuoteMetaBrick with quote_number, quoted_at, expires_at fields
- Create DetailTasksBrick with task list table (number, name, description, price, status)
- Create FooterTermsBrick for terms field from entities
- Create FooterSummaryBrick for summary field from entities
- Update FooterNotesBrick to use 'footer' field instead of 'footer_notes'
- Create 10 Blade templates (preview + render) for new bricks
- Update ReportBricksCollection to include all 11 bricks
- Add 60+ translation keys for new bricks
- Create MasonTemplateStorage service - stores Mason JSON directly (no BlockDTO)
- Simplify ReportBuilder - removed BlockDTO/MasonStorageAdapter dependencies
- Storage now: Mason JSON → filesystem (no transformation)

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Refactor brick actions to use Mason's standard fillForm pattern

- Update all 11 brick classes to use simplified fillForm pattern
- Change from manual config extraction to: fillForm(fn ($args) => $args['config'] ?? null)
- Makes full use of Mason's BrickAction pattern as shown in documentation
- Cleaner, more maintainable code that follows Mason best practices
- Reduces code duplication across all brick configuration actions

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Add 6 new Mason bricks for enhanced reporting capabilities

- DetailInvoiceProductBrick: Product-focused invoice line items with SKU support
- DetailInvoiceProjectBrick: Project-based invoice items with hour tracking
- DetailQuoteProductBrick: Product-focused quote line items
- DetailQuoteProjectBrick: Project-based quote items with task grouping
- DetailCustomerAgingBrick: Customer aging report with 30/60/90 day buckets
- DetailExpenseBrick: Expense tracking with category and vendor support
- Created 12 Blade templates (preview + render for each brick)
- Updated ReportBricksCollection to include all 6 new bricks
- Added 60+ translation keys for all new UI elements
- All bricks follow Mason's standard fillForm pattern

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Update Modules/Core/Filament/Admin/Resources/ReportTemplates/Pages/ReportBuilder.php

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Add authorization and fix XSS vulnerabilities in Mason bricks

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Update resources/lang/en/ip.php

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update Modules/Core/Services/MasonStorageAdapter.php

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fix test assertions, Blade syntax, and unused imports per code review

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Add test for MasonTemplateStorage save/load flow

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Update Modules/Core/Tests/Feature/ReportBuilderMasonIntegrationTest.php

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
nielsdrost7 added a commit that referenced this pull request May 25, 2026
* Branch Report Builder initial

* Removed Invoices temporarily

* 126: Peppo;l

* temporary-total

* temp

* Delete Modules/ReportBuilder directory

* Composer correct

* Composer correct

* Update pint.yml

* Fix Filament action imports, grid calculations, and refactor test mocks to fakes in Report Builder (#351)

* Initial plan

* Fix ReportBlocksTable imports, actions, GridSnapperService, test mock, and CSS syntax

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Refactor tests to use Storage::fake() instead of mocking repository

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Change actions to recordActions in ReportBlocksTable

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* merged in develop branch

* Initial plan

* Add import:db command with service and tests

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Add table existence checks to import service

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Add documentation and additional tests for import functionality

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Fix security issues and improve code quality based on review

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Add implementation summary document

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Implement modular import architecture with separate services

- Add 'import_v1' database connection in config
- Create ImportServiceInterface and AbstractImportService base
- Implement modular import services:
  * TaxRatesImportService
  * ProductsImportService (categories, units, products)
  * ClientsImportService (relations, contacts, addresses)
  * NumberingImportService (invoice groups)
  * InvoicesImportService (with InvoiceStatus enum)
  * QuotesImportService (with QuoteStatus enum)
  * PaymentsImportService (with PaymentMethod enum)
- Create ImportOrchestrator to coordinate all services
- Update command to read from storage/app/private/imports
- Use Laravel DB connections instead of shell restoration

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Add remaining import services for complete coverage

- UsersImportService (ip_users)
- ProjectsImportService (ip_projects, ip_tasks)
- EmailTemplatesImportService (ip_email_templates)
- CustomFieldsImportService (ip_custom_fields, ip_custom_values)
- SettingsImportService (ip_settings)
- NotesImportService (ip_notes)
- Update ImportOrchestrator to include all services
- Add required ID mappings (users, projects, custom_fields)

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Add comprehensive PHPUnit tests for import services

- TaxRatesImportServiceTest with 7 test cases
- ProductsImportServiceTest with 7 test cases
- ClientsImportServiceTest with 8 test cases
- Each test includes edge case coverage
- Tests use RefreshDatabase and proper setup/teardown
- All tests follow AAA (Arrange, Act, Assert) pattern

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Refactor to use ModelType enum and add numbering logic

- Create ModelType enum for model class mappings
- Refactor CustomFieldsImportService to use ModelType enum
- Refactor NotesImportService to use ModelType enum
- Add applyNumberingLogic method to NumberingImportService
- Call numbering logic after all imports in ImportOrchestrator
- Ensures numbering won't fail after import

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update Modules/Core/Tests/Feature/ImportInvoicePlaneV1CommandTest.php

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Update Modules/Core/Tests/Feature/ImportInvoicePlaneV1CommandTest.php

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Update Modules/Core/Services/Import/EmailTemplatesImportService.php

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fix Contact import to use first_name/last_name and add communications

- Split contact_name into first_name and last_name fields
- Import email and phone as Communication records
- Replace ->run() with ->assertSuccessful() in all tests
- Update ClientsImportServiceTest to verify name splitting and communications
- EmailTemplatesImportService already uses correct column names (verified)

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Fix critical issues in import services and documentation

- ImportOrchestrator: Scope users to company via whereHas, attach new users
- UsersImportService: Validate emails before import
- PaymentsImportService: Use PaymentStatus::COMPLETED enum instead of 'paid'
- InvoicesImportService: Optimize item loading with groupBy (prevent N+1 queries)
- QuotesImportService: Optimize item loading with groupBy (prevent N+1 queries)
- ImportInvoicePlaneV1CommandTest: Use enum comparisons and filter by amount
- IMPORT_README.md: Fix documentation to match actual command signature (filename, not path)
- IMPORT_README.md: Update cleanup notes (database kept for debugging)

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Fix field names and add security improvements

- ClientsImportService: Use postal_code/state_or_province for Address
- ClientsImportService: Use contactable_type/contactable_value for Communication
- NotesImportService: Use $modelType->value instead of non-existent mapModelType()
- NumberingImportService: Use NumberingType::INVOICE enum instead of string
- ImportOrchestrator: Add database name validation (alphanumeric + $_)
- ImportOrchestrator: Catch \Throwable instead of \Exception for better error handling

Agent-Logs-Url: https://github.com/InvoicePlane/InvoicePlane-v2/sessions/51c0a25b-ecc7-4eaf-b336-17e8eb8d4430

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Fix multi-tenancy, numbering logic, and model field names

- UsersImportService: Attach users to company (both new and existing)
- NumberingImportService: Use NumberingType enum values in where clauses
- NumberingImportService: Fix max() logic - pluck all numbers, extract numeric parts, find max
- SettingsImportService: Remove company_id (Settings table is global)
- TaxRatesImportService: Use correct field names (name, rate, code, tax_rate_type)
- TaxRatesImportService: Add TaxRateType::SALES as default type

Agent-Logs-Url: https://github.com/InvoicePlane/InvoicePlane-v2/sessions/981e7574-6fa1-4881-9063-eaee7c105870

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* fix: apply CodeRabbit auto-fixes

Fixed 5 file(s) based on 17 unresolved review comments.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>

* Fix remaining issues from code review

- CustomFieldsImportService: Add resolveModelId() method to fix fatal error
- CustomFieldsImportService: Use ModelType::fromString()->value directly
- ImportOrchestrator: Remove unused Storage import
- ImportOrchestrator: Create database on import_v1 server using PDO
- ClientsImportService: Remove unused ip_client_notes from getTables()
- ImportInvoicePlaneV1CommandTest: Fix argument name (filename not dumpfile)
- ImportInvoicePlaneV1CommandTest: Copy fixture to storage/app/private/imports
- Unit tests: Configure import_v1 to use SQLite in-memory for CI compatibility
- IMPLEMENTATION_SUMMARY.md: Fix usage examples (filename only, not full path)

Agent-Logs-Url: https://github.com/InvoicePlane/InvoicePlane-v2/sessions/a0fb0fe9-f728-4766-a34e-ad002b4363a1

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Update Modules/Core/Commands/IMPORT_README.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Niels Drost <nielsdrost7@gmail.com>
Co-authored-by: Niels Drost <47660417+nielsdrost7@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants