Repository navigation
Closed
Labels
refinedRefined with SMART plan / test suggestionsRefined with SMART plan / test suggestions
Milestone
Description
SMART Plan — As an Admin, in the company Panel I want to be able to view, edit, delete Payment Methods
Specific
Add a PaymentMethodResource to the Company panel (/{tenant}). The resource manages payment methods scoped to the current tenant company and provides a full CRUD interface: list, create, edit, and delete. It is accessible only to customer_admin or elevated roles.
Measurable
- A
customer_admincan view the list of payment methods for their company. - Edit and delete actions complete without errors and persist/remove data correctly.
- Payment methods from other companies do not appear in the list (tenant isolation enforced).
- A
customerrole cannot access the resource.
Achievable
- Create (or verify)
PaymentMethodmodel withBelongsToCompanytrait —Modules/Payments/Models/PaymentMethod.php - Create migration for
payment_methodstable if it doesn't exist —Modules/Payments/Database/Migrations/ - Create
PaymentMethodResourcefor the company panel —Modules/Payments/Filament/Company/Resources/PaymentMethods/PaymentMethodResource.php - Create
ListPaymentMethods,CreatePaymentMethod,EditPaymentMethodpages under the resource'sPages/directory. - Register the resource in
CompanyPanelProvider—Modules/Core/Providers/CompanyPanelProvider.php - Add role guard restricting access to
customer_adminand elevated roles.
Relevant
Payment methods are the mechanism by which a company's customers pay invoices. Company admins must be able to configure, update, and remove payment options (e.g. bank transfer details, PayPal address) without involving a platform admin.
Time-bound
Sprint 6.
Arrange · Act · Assert
// Modules/Payments/Tests/Feature/Company/PaymentMethodResourceTest.php
#[Test]
public function customer_admin_can_list_payment_methods_in_company_panel(): void
{
/* Arrange */
$method = PaymentMethod::factory()->for($this->company)->create();
$otherMethod = PaymentMethod::factory()->create(); // different company
/* Act */
$response = $this->testLivewire(ListPaymentMethods::class);
/* Assert */
$response->assertSuccessful()
->assertCanSeeTableRecords([$method])
->assertCanNotSeeTableRecords([$otherMethod]);
}
#[Test]
public function customer_admin_can_delete_a_payment_method(): void
{
/* Arrange */
$method = PaymentMethod::factory()->for($this->company)->create();
/* Act */
$this->testLivewire(ListPaymentMethods::class)
->callTableAction(DeleteAction::class, $method)
->assertHasNoErrors();
/* Assert */
$this->assertDatabaseMissing('payment_methods', ['id' => $method->id]);
}Reacted by coderabbitai
Metadata
Metadata
Assignees
Labels
refinedRefined with SMART plan / test suggestionsRefined with SMART plan / test suggestions
Activity
coderabbitai commentedon Dec 28, 2025
📝 CodeRabbit Plan Mode
Generate an implementation plan and prompts that you can use with your favorite coding agent.
Examples
🔗 Similar Issues
Possible Duplicates
Related Issues
👤 Suggested Assignees
🧪 Issue enrichment is currently in open beta.
You can configure auto-planning by selecting labels in the issue_enrichment configuration.
To disable automatic issue enrichment, add the following to your
.coderabbit.yaml:💬 Have feedback or questions? Drop into our discord!
nielsdrost7 commentedon Jan 2, 2026
@coderabbitai make pull-request with AAA test Scenario's: Arrange, Act, Assert. And also make sure you test edge cases
coderabbitai commentedon Jan 2, 2026
Coding Plan
Approach
Convert Payment Methods from an enum-based system to a company-scoped database model with full CRUD capabilities through the Filament admin panel, including comprehensive AAA-structured tests and edge case coverage.
Observations
The application is a multi-tenant Laravel system using Filament for admin panels. Payment Methods currently exist as an enum (PaymentMethod.php) with 5 cases (bank_transfer, cash, credit_card, paypal, stripe) that are directly cast on the Payment model's payment_method string column. The codebase follows a modular architecture where company-scoped resources use the BelongsToCompany trait, Filament resources delegate to separate form/table configurators, and tests extend AbstractCompanyPanelTestCase. The Payments module includes models, migrations, services, Filament resources, and comprehensive business logic for payment operations.
Assumptions
Assumption 1: Should Payment Methods maintain backward compatibility with the enum structure?
Options Considered:
Chosen Option: 3
Rationale: This provides the cleanest migration path—the enum becomes a reference for seeding default payment methods per company, while the model enables CRUD. Existing Payment records migrate to foreign key relationships, and the enum can later be deprecated once all references are updated.
💡 User Tips
Regenerate the plan with different choices with
@coderabbitai <feedback>.Implementation Steps
Phase 1: Database Schema and Model Creation
Create the PaymentMethod model as a company-scoped entity and migrate existing enum-based payment data to the new structure.
Task 1: Create PaymentMethod Model and Initial Migration
Create a company-scoped PaymentMethod model that will replace the enum-based system.
Modules/Payments/Models/PaymentMethod.phpmodel with BelongsToCompany traitcreate_payment_methods_table.phpinModules/Payments/Database/Migrations/Task 2: Seed Default Payment Methods from Enum
Create a data migration to populate payment_methods table with default values from the existing enum for all companies.
seed_payment_methods_from_enum.phpinModules/Payments/Database/Migrations/Task 3: Add Foreign Key Relationship to Payments Table
Migrate the Payment model from using an enum-cast string to a foreign key relationship with PaymentMethod.
add_payment_method_id_to_payments_table.phpinModules/Payments/Database/Migrations/Task 4: Update Payment Model
Modify the Payment model to use the new relationship while maintaining backward compatibility temporarily.
Modules/Payments/Models/Payment.phpto add belongsTo relationship for paymentMethod()🤖 Prompt for AI agents
Phase 2: Filament CRUD Interface for Payment Methods
Build the Filament admin interface for managing Payment Methods in the company panel following established patterns.
Task 1: Create PaymentMethod Filament Resource
Create the Filament resource structure for Payment Methods in the company panel.
Modules/Payments/Filament/Company/Resources/PaymentMethods/PaymentMethodResource.phpextending BaseResourceTask 2: Create PaymentMethod Form Configurator
Build the form schema for creating and editing Payment Methods.
Modules/Payments/Filament/Company/Resources/PaymentMethods/Schemas/PaymentMethodForm.phpconfigurator classTask 3: Create PaymentMethod Table Configurator
Build the table configuration for listing and managing Payment Methods.
Modules/Payments/Filament/Company/Resources/PaymentMethods/Schemas/PaymentMethodsTable.phpconfigurator classTask 4: Create PaymentMethod List Page
Create the list page component for the Payment Methods resource.
Modules/Payments/Filament/Company/Resources/PaymentMethods/Pages/ListPaymentMethods.phpextending ListRecordsTask 5: Add Deletion Protection Logic
Implement business logic to prevent deletion of Payment Methods that are in use by existing Payments.
Modules/Payments/Models/PaymentMethod.phpto add hasMany relationship to PaymentModules/Payments/Observers/directory🤖 Prompt for AI agents
Phase 3: Update Payment Dependencies
Update all components that interact with Payment Methods to use the new relationship model.
Task 1: Update Payment Form to Use Relationship
Modify the Payment form to select from company's PaymentMethod records instead of enum cases.
Modules/Payments/Filament/Company/Resources/Payments/Schemas/PaymentForm.phpTask 2: Update PaymentService
Modify the PaymentService to handle payment_method_id instead of enum values.
Modules/Payments/Services/PaymentService.phpcreate methodTask 3: Update Payment Factory and Seeder
Update test data generation to use PaymentMethod relationships.
Modules/Payments/Database/Factories/PaymentFactory.phpModules/Payments/Database/Seeders/PaymentsSeeder.phpto ensure PaymentMethod records exist before creating Payments🤖 Prompt for AI agents
Phase 4: Payment Method CRUD Tests with AAA Structure
Create comprehensive test coverage for Payment Method CRUD operations with explicit Arrange-Act-Assert structure.
Task 1: Create Test File Structure and Helpers
Set up the test file with proper organization and reusable helper methods.
Modules/Payments/Tests/Feature/PaymentMethodsTest.phpextending AbstractCompanyPanelTestCase#[Group('payment-methods')]Task 2: Test Payment Method List View - Happy Path
Verify that users can successfully view their company's payment methods list.
Write test:
test_user_can_view_payment_methods_list()Arrange:
Act:
Assert:
Task 3: Test Payment Method List View - Empty State
Verify proper handling when company has no payment methods.
Write test:
test_payment_methods_list_shows_empty_state_when_no_records()Arrange:
Act:
Assert:
Task 4: Test Payment Method Creation - Valid Data
Test successful creation of a new payment method with valid data.
Write test:
test_user_can_create_payment_method_with_valid_data()Arrange:
Act:
Assert:
Task 5: Test Payment Method Creation - Required Field Validation
Test that required fields are validated during creation.
Write test:
test_payment_method_creation_requires_name_field()Arrange:
Act:
Assert:
Task 6: Test Payment Method Creation - Name Length Validation
Test that name field respects maximum length constraints.
Write test:
test_payment_method_name_cannot_exceed_maximum_length()Arrange:
Act:
Assert:
Task 7: Test Payment Method Creation - Duplicate Name Handling
Test that duplicate payment method names are handled appropriately within same company.
Write test:
test_company_can_create_payment_methods_with_duplicate_names()Arrange:
Act:
Assert:
Task 8: Test Payment Method Creation - Special Characters in Name
Test that special characters in payment method names are handled correctly.
Write test:
test_payment_method_name_accepts_special_characters()Arrange:
Act:
Assert:
Task 9: Test Payment Method Edit - Happy Path
Test successful editing of an existing payment method.
Write test:
test_user_can_edit_existing_payment_method()Arrange:
Act:
Assert:
Task 10: Test Payment Method Edit - Validation on Update
Test that validation rules apply when editing payment methods.
Write test:
test_editing_payment_method_validates_required_fields()Arrange:
Act:
Assert:
Task 11: Test Payment Method Edit - Preserving Relationships
Test that editing a payment method preserves its relationships with existing payments.
Write test:
test_editing_payment_method_preserves_existing_payment_relationships()Arrange:
Act:
Assert:
Task 12: Test Payment Method Deletion - Unused Method
Test successful deletion of a payment method with no associated payments.
Write test:
test_user_can_delete_unused_payment_method()Arrange:
Act:
Assert:
Task 13: Test Payment Method Deletion - Method In Use
Test that payment methods with associated payments cannot be deleted.
Write test:
test_user_cannot_delete_payment_method_in_use()Arrange:
Act:
Assert:
Task 14: Test Payment Method Deletion - Multiple Payments
Test deletion prevention when payment method has multiple associated payments.
Write test:
test_cannot_delete_payment_method_with_multiple_payments()Arrange:
Act:
Assert:
Task 15: Test Payment Method Deletion - After Payments Deleted
Test that payment method becomes deletable after all associated payments are removed.
Write test:
test_can_delete_payment_method_after_payments_removed()Arrange:
Act:
Assert:
Task 16: Test Company Scoping - List Isolation
Verify that payment methods list only shows company's own records.
Write test:
test_payment_methods_list_scoped_to_users_company()Arrange:
Act:
Assert:
Task 17: Test Company Scoping - Edit Isolation
Verify that users cannot edit payment methods from other companies.
Write test:
test_user_cannot_edit_other_company_payment_methods()Arrange:
Act:
Assert:
Task 18: Test Company Scoping - Delete Isolation
Verify that users cannot delete payment methods from other companies.
Write test:
test_user_cannot_delete_other_company_payment_methods()Arrange:
Act:
Assert:
Task 19: Test Company Scoping - Cross-Company Creation
Verify that created payment methods are automatically scoped to user's company.
Write test:
test_created_payment_methods_automatically_scoped_to_users_company()Arrange:
Act:
Assert:
Task 20: Test Active/Inactive Status Toggle
Test toggling payment method activation status.
Write test:
test_payment_method_can_be_activated_and_deactivated()Arrange:
Act:
Assert:
Task 21: Test Bulk Activation Action
Test bulk action to activate multiple payment methods at once.
Write test:
test_can_bulk_activate_multiple_payment_methods()Arrange:
Act:
Assert:
Task 22: Test Bulk Deactivation Action
Test bulk action to deactivate multiple payment methods at once.
Write test:
test_can_bulk_deactivate_multiple_payment_methods()Arrange:
Act:
Assert:
Task 23: Test Sort Order Functionality
Test that payment methods respect custom sort_order values.
Write test:
test_payment_methods_display_in_sort_order()Arrange:
Act:
Assert:
Task 24: Test Filter by Active Status
Test table filtering by is_active status.
Write test:
test_can_filter_payment_methods_by_active_status()Arrange:
Act:
Assert:
🤖 Prompt for AI agents
Phase 5: Payment Integration Tests with AAA Structure
Test that Payment model correctly integrates with the new PaymentMethod relationship.
Task 1: Test Payment Creation with Valid Payment Method
Test creating payments using valid payment method foreign keys.
Write test:
test_can_create_payment_with_valid_payment_method_id()Arrange:
Act:
Assert:
Task 2: Test Payment Creation with Invalid Payment Method
Test that creating payments with non-existent payment method IDs fails validation.
Write test:
test_cannot_create_payment_with_invalid_payment_method_id()Arrange:
Act:
Assert:
Task 3: Test Payment Creation with Other Company's Payment Method
Test that payments cannot use payment methods from different companies.
Write test:
test_cannot_create_payment_with_other_company_payment_method()Arrange:
Act:
Assert:
Task 4: Test Payment Form Shows Only Active Methods
Test that payment creation form dropdown only displays active payment methods.
Write test:
test_payment_form_only_shows_active_payment_methods()Arrange:
Act:
Assert:
Task 5: Test Payment Form Shows Company-Scoped Methods
Test that payment form only shows payment methods from user's company.
Write test:
test_payment_form_only_shows_users_company_payment_methods()Arrange:
Act:
Assert:
Task 6: Test Payment Factory with PaymentMethod
Test that payment factory creates valid payment method relationships.
Write test:
test_payment_factory_creates_valid_payment_methods()Arrange:
Act:
Assert:
Task 7: Test Payment Relationship Query Performance
Test that payment method relationships use efficient queries without N+1 issues.
Write test:
test_payment_relationship_queries_are_efficient()Arrange:
Act:
Assert:
Task 8: Test Payment Method Updates Reflect in Payments
Test that updating a payment method's name reflects in associated payments.
Write test:
test_payment_method_name_updates_visible_to_associated_payments()Arrange:
Act:
Assert:
Task 9: Test Payment Deletion Does Not Affect Payment Method
Test that deleting payments does not cascade delete the payment method.
Write test:
test_deleting_payment_does_not_delete_payment_method()Arrange:
Act:
Assert:
Task 10: Test Payment Seeder with PaymentMethods
Test that payment seeder creates valid data with payment method relationships.
Write test:
test_payment_seeder_creates_valid_payment_methods()Arrange:
Act:
Assert:
🤖 Prompt for AI agents
Phase 6: Edge Cases and Error Handling Tests
Test edge cases, boundary conditions, and error scenarios with explicit AAA structure.
Task 1: Test Concurrent Payment Method Creation
Test handling of concurrent payment method creation attempts.
Write test:
test_concurrent_payment_method_creation_handles_race_conditions()Arrange:
Act:
Assert:
Task 2: Test Payment Method with Extremely Long Description
Test boundary conditions for description field.
Write test:
test_payment_method_description_handles_long_text()Arrange:
Act:
Assert:
Task 3: Test Payment Method with Null Optional Fields
Test that nullable fields accept null values correctly.
Write test:
test_payment_method_accepts_null_for_optional_fields()Arrange:
Act:
Assert:
Task 4: Test Payment Method Sort Order Boundaries
Test sort order with negative, zero, and very large values.
Write test:
test_payment_method_sort_order_accepts_various_integer_values()Arrange:
Act:
Assert:
Task 5: Test Payment Method Name with Only Whitespace
Test validation of names containing only whitespace.
Write test:
test_payment_method_name_cannot_be_only_whitespace()Arrange:
Act:
Assert:
Task 6: Test Payment Method Deactivation Impact on Existing Payments
Test that deactivating a payment method does not affect existing payments using it.
Write test:
test_deactivating_payment_method_does_not_affect_existing_payments()Arrange:
Act:
Assert:
Task 7: Test Payment Method with Unicode Characters
Test that payment method names support international characters.
Write test:
test_payment_method_name_supports_unicode_characters()Arrange:
Act:
Assert:
Task 8: Test Payment Method Deletion with Large Number of Payments
Test deletion prevention with high volume of associated payments.
Write test:
test_cannot_delete_payment_method_with_many_payments()Arrange:
Act:
Assert:
Task 9: Test Payment Creation Form After All Methods Deactivated
Test payment form behavior when no active payment methods exist.
Write test:
test_payment_form_shows_message_when_no_active_payment_methods()Arrange:
Act:
Assert:
Task 10: Test Payment Method Observer Exception Handling
Test that observer exceptions are caught and handled gracefully.
Write test:
test_payment_method_observer_handles_exceptions_gracefully()Arrange:
Act:
Assert:
🤖 Prompt for AI agents
🚀 Next Steps
🤖 All AI agent prompts combined
💡 Iterate on the plan with:
@coderabbitai <feedback>💬 Have feedback or questions? Drop into our discord!
nielsdrost7 commentedon Jan 3, 2026
@coderabbitai make test Scenario's, including the subissues: Arrange, Act, Assert. And also make sure you test edge cases
coderabbitai commentedon Jan 3, 2026
I've updated the plan above based on your feedback. Ready to proceed when you are!
[-]As an Admin, in the company Panel I want to be able to view, edit, delete Payment Methods[/-][+][Settings]: Company panel — manage Payment Methods[/+]nielsdrost7 commentedon Jul 24, 2026
SMART Plan — Company panel — manage Payment Methods
Specific
Add a
PaymentMethodResourceto the Company panel (/{tenant}/payment-methods). Provides full CRUD for Payment Methods scoped to the current tenant company. Only accessible tocustomer_adminrole.Measurable
Achievable
Modules/Payments/Models/PaymentMethod.php(or similar) hasBelongsToCompanytrait.Modules/Payments/Filament/Company/Resources/PaymentMethodResource.php.CompanyPanelProvider.Relevant
Companies often add/retire payment channels (PayPal, Stripe, bank transfer) based on business needs. A CRUD screen lets them self-manage without admin involvement.
Time-bound
Sprint 6.
feat(InvoicePlane#237,InvoicePlane#241): per-company enabled payment …
nielsdrost7 commentedon Jul 24, 2026
Implemented on
feature/235-243-company-settings-cluster, combined with #241 since they're the same feature — see that issue's comment for details.PaymentMethodstays the existing fixed enum (Modules/Payments/Enums/PaymentMethod.php, used only asPayment::payment_method's cast) rather than becoming a new CRUD-able entity: there's nothing else per-company to create/edit given a fixed, hardcoded set of gateway types (bank transfer, cash, credit card, PayPal, Stripe). The company-configurable surface is which of those are enabled — that's what this delivers.feat(InvoicePlane#237,InvoicePlane#241): per-company enabled payment …