Skip to content

[Settings]: Admin panel — assign Users to companies #234

Closed

Description

@nielsdrost7

SMART Plan — As an Admin, in the admin Panel I want to be able to assign Users to multiple companies

Specific

In the Admin panel (/admin), the CompanyResource table view gains a bulk action called "Assign User". When one or more companies are selected and the action is triggered, a modal opens with a searchable select of all User records. On confirmation, the selected user is attached to every selected company via the existing company_user pivot table.

Measurable

  • Selecting 2+ companies and triggering the bulk action opens a modal with a User select.
  • After confirmation, a company_user row exists for the selected user in each selected company.
  • Already-attached users are not duplicated (use syncWithoutDetaching or attach with existence check).
  • A Filament success notification confirms how many companies were updated.

Achievable

  1. Verify company_user pivot table and Company::users() / User::companies() BelongsToMany relations exist — Modules/Core/Models/Company.php, Modules/Core/Models/User.php
  2. Create AssignUserBulkAction Filament bulk action class — Modules/Core/Filament/Admin/Resources/Companies/Tables/Actions/AssignUserBulkAction.php
  3. Register the bulk action on CompanyResource table — Modules/Core/Filament/Admin/Resources/Companies/Tables/CompanyTable.php

Relevant

Platform admins frequently need to grant a support or billing user access to a portfolio of company accounts simultaneously. This bulk action eliminates the need to open each company individually and add the user one by one.

Time-bound

Sprint 6.


Arrange · Act · Assert

// Modules/Core/Tests/Feature/Admin/CompanyUserBulkActionTest.php

#[Test]
public function it_assigns_user_to_multiple_companies(): void
{
    /* Arrange */
    $companies = Company::factory()->count(2)->create();
    $user      = User::factory()->create(['is_active' => true]);
    $ids       = $companies->pluck('id')->all();

    /* Act */
    Livewire::actingAs($this->superAdmin())
        ->test(ListCompanies::class)
        ->callBulkAction('assignUser', $ids, ['user_id' => $user->id])
        ->assertHasNoErrors();

    /* Assert */
    foreach ($companies as $company) {
        $this->assertDatabaseHas('company_user', [
            'company_id' => $company->id,
            'user_id'    => $user->id,
        ]);
    }
}

Activity

  1. coderabbitai commented on Dec 28, 2025

    @coderabbitai
    Contributor

    📝 CodeRabbit Plan Mode

    Generate an implementation plan and prompts that you can use with your favorite coding agent.

    • Create Plan
    Examples

    🔗 Similar Issues

    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:

    issue_enrichment:
      auto_enrich:
        enabled: false

    💬 Have feedback or questions? Drop into our discord!

  2. added this to the v2.0.0-alpha milestone on Dec 28, 2025
  3. nielsdrost7 commented on Jan 2, 2026

    @nielsdrost7
    CollaboratorAuthor

    @coderabbitai make pull-request with AAA test Scenario's: Arrange, Act, Assert. And also make sure you test edge cases

  4. coderabbitai commented on Jan 2, 2026

    @coderabbitai
    Contributor

    Coding Plan

    Approach

    Create comprehensive PHPUnit feature tests following the AAA pattern to verify company assignment functionality for users in the admin panel. Tests will be written using a test-driven development approach to define expected behavior before implementation.

    Observations

    The application uses a modular Laravel architecture with Filament 3.x for the admin panel. The Core module contains user management functionality organized with separated concerns: UserResource delegates to UserForm for form fields and UsersTable for table configuration. A many-to-many relationship already exists between User and Company models via a company_user pivot table with an is_owner attribute. Testing follows a consistent AAA pattern using PHPUnit with AbstractAdminPanelTestCase providing base test setup with user and company fixtures.

    Assumptions
    Assumption 1: Where should the new tests be located?

    Options Considered:

    • Add all tests to existing Modules/Core/Tests/Feature/UsersTest.php
    • Create new dedicated file Modules/Core/Tests/Feature/UserCompanyAssignmentTest.php

    Chosen Option: 2

    Rationale: Create a dedicated test file to keep company assignment tests organized separately and make it easier to locate and maintain this specific functionality's test coverage.

    💡 User Tips

    Regenerate the plan with different choices with @coderabbitai <feedback>.

    Implementation Steps

    Implement Comprehensive Tests for Company Assignment

    Create feature tests following the AAA pattern to verify all aspects of company assignment functionality. These tests define expected behavior using test-driven development and will serve as specifications for the feature implementation.

    Task 1: Test Company Column Display in Users Table

    Verify that company assignments are correctly displayed in the users table

    • Create test in Modules/Core/Tests/Feature/UserCompanyAssignmentTest.php extending AbstractAdminPanelTestCase
    • Arrange: Create user with multiple company assignments using factories and attach() with is_owner pivot values
    • Act: Render the ListUsers Livewire component as an admin user
    • Assert: Verify company names appear in the table, verify correct display format (badges or comma-separated list)
    Task 2: Test RelationManager Company List Display

    Verify the RelationManager correctly shows assigned companies with pivot attributes

    • Arrange: Create user with 2-3 company assignments including varied is_owner values
    • Act: Mount the CompaniesRelationManager component for that user
    • Assert: Verify all assigned companies appear in the relation manager table, verify is_owner status is displayed correctly for each company
    Task 3: Test Attaching Companies via RelationManager

    Verify that companies can be attached through the RelationManager with explicit is_owner values

    • Arrange: Create user with one company, create additional company to attach
    • Act: Use Livewire test to call attach action with company ID and is_owner value (true)
    • Assert: Verify pivot record exists in database with correct is_owner value, verify user->companies() relationship includes new company, verify pivot attributes are correct
    Task 4: Test Attaching Company Without is_owner Flag

    Verify default behavior when is_owner is not specified during attachment

    • Arrange: Create user and company
    • Act: Attach company without specifying is_owner in form data
    • Assert: Verify company is attached with is_owner defaulting to false in pivot table
    Task 5: Test Detaching Companies via RelationManager

    Verify companies can be removed from users individually

    • Arrange: Create user with multiple company assignments (3-4 companies)
    • Act: Call detach/delete action for one specific company
    • Assert: Verify pivot record is removed from database, verify user->companies() no longer includes detached company, verify other assignments remain intact with correct pivot data
    Task 6: Test Bulk Detach of Multiple Companies

    Verify bulk deletion works correctly for multiple companies at once

    • Arrange: Create user with 3+ company assignments
    • Act: Select multiple companies and call bulk delete action
    • Assert: Verify all selected companies are detached from user, verify remaining assignments are unaffected, verify no orphaned pivot records exist
    Task 7: Test Edge Case - Attaching Already Assigned Company

    Verify behavior when attempting to attach a company that's already assigned to the user

    • Arrange: Create user with company A already assigned
    • Act: Attempt to attach company A again through RelationManager attach action
    • Assert: Verify appropriate validation error or silent handling (depending on Filament's default behavior), verify no duplicate pivot records exist in database
    Task 8: Test Edge Case - Updating Pivot Attribute

    Verify that is_owner can be toggled for existing assignments

    • Arrange: Create user assigned to company with is_owner = false
    • Act: Toggle is_owner to true via ToggleColumn interaction or update action
    • Assert: Verify pivot record is updated in database with new is_owner value, verify no duplicate records created, verify other pivot data remains unchanged
    Task 9: Test Edge Case - User with No Companies

    Verify graceful handling when user has no company assignments

    • Arrange: Create user with no company assignments
    • Act: View user in table and open RelationManager
    • Assert: Verify users table shows appropriate empty state or placeholder for companies column, verify RelationManager shows empty state message, verify no errors occur
    Task 10: Test Permission and Authorization

    Verify that only admin users can manage company assignments

    • Arrange: Create non-admin user (regular user without admin role) and admin user
    • Act: Attempt to access UserResource and CompaniesRelationManager as non-admin
    • Assert: Verify non-admin users cannot access UserResource pages, verify non-admin users cannot access or modify company assignments (may already be handled by existing admin panel authorization)
    🤖 Prompt for AI agents
    This phase implements comprehensive feature tests for user-company assignment
    functionality using TDD approach. The tests define expected behavior before
    implementation.
    
    Create `Modules/Core/Tests/Feature/UserCompanyAssignmentTest.php` extending
    AbstractAdminPanelTestCase:
    
    **Table Display Tests:**
    - Test company column shows multiple assignments correctly with
    badges/comma-separated format
    - Test RelationManager displays assigned companies with is_owner status
    
    **CRUD Operation Tests:**
    - Test attaching companies with explicit is_owner value (true)
    - Test attaching companies without is_owner (verify default false)
    - Test detaching individual companies (verify pivot removal, other assignments
    intact)
    - Test bulk detach of multiple companies (verify selected removed, others
    unaffected)
    
    **Edge Case Tests:**
    - Test attaching already assigned company (verify validation error or silent
    handling, no duplicates)
    - Test toggling is_owner pivot attribute (verify update without duplicates)
    - Test user with no companies (verify empty state in table and RelationManager)
    - Test authorization (verify non-admin cannot access UserResource or manage
    assignments)
    
    Use AAA pattern: Arrange (create user/company fixtures with factories), Act
    (render Livewire components, call actions), Assert (verify database state and
    UI)
    

    🚀 Next Steps

    🤖 All AI agent prompts combined
    This phase implements comprehensive feature tests for user-company assignment
    functionality using TDD approach. The tests define expected behavior before
    implementation.
    
    Create `Modules/Core/Tests/Feature/UserCompanyAssignmentTest.php` extending
    AbstractAdminPanelTestCase:
    
    **Table Display Tests:**
    - Test company column shows multiple assignments correctly with
    badges/comma-separated format
    - Test RelationManager displays assigned companies with is_owner status
    
    **CRUD Operation Tests:**
    - Test attaching companies with explicit is_owner value (true)
    - Test attaching companies without is_owner (verify default false)
    - Test detaching individual companies (verify pivot removal, other assignments
    intact)
    - Test bulk detach of multiple companies (verify selected removed, others
    unaffected)
    
    **Edge Case Tests:**
    - Test attaching already assigned company (verify validation error or silent
    handling, no duplicates)
    - Test toggling is_owner pivot attribute (verify update without duplicates)
    - Test user with no companies (verify empty state in table and RelationManager)
    - Test authorization (verify non-admin cannot access UserResource or manage
    assignments)
    
    Use AAA pattern: Arrange (create user/company fixtures with factories), Act
    (render Livewire components, call actions), Assert (verify database state and
    UI)
    
    💡 Iterate on the plan with: @coderabbitai <feedback>
    Example Feedback
    - @coderabbitai You can skip phase 3. Add a simple unit test case for phase 2.
    - @coderabbitai For assumption 1 go ahead with option 3 and replan.
    

    💬 Have feedback or questions? Drop into our discord!

  5. nielsdrost7 commented on Jan 3, 2026

    @nielsdrost7
    CollaboratorAuthor

    @coderabbitai

    • Arrange: Create non-admin user and admin user
    • Act: Attempt to access UserResource and CompaniesRelationManager as non-admin
    • Assert: Verify non-admin users cannot access or modify company assignments (may already be handled by existing admin panel authorization)
    🤖 Prompt for AI agents
    Create comprehensive feature tests following the AAA pattern to verify company
    assignment functionality.
    
    In `Modules/Core/Tests/Feature/UsersTest.php` or new
    `UserCompanyAssignmentTest.php`:
    - Test company column displays correctly in users table with multiple
    assignments
    - Test RelationManager displays assigned companies with correct is_owner status
    - Test attaching companies with and without is_owner flag (verify default false)
    - Test detaching companies individually and in bulk
    - Test edge cases:
      - Attempting to attach already assigned company
      - Updating is_owner pivot attribute via toggle
      - User with no companies shows empty state
      - Authorization for admin-only access
    
    Use AAA pattern: Arrange (create fixtures), Act (render/interact with
    components), Assert (verify database and UI state)
    

    Create a PR with those phpunit tests

  6. coderabbitai commented on Jan 3, 2026

    @coderabbitai
    Contributor

    I've updated the plan above based on your feedback. Ready to proceed when you are!

  7. changed the title [-]As an Admin, in the admin Panel I want to be able to assign Users to multiple companies[/-] [+][Settings]: Admin panel — assign Users to companies[/+] on Jun 13, 2026
  8. nielsdrost7 commented on Jul 24, 2026

    @nielsdrost7
    CollaboratorAuthor

    SMART Plan — Admin panel — assign Users to companies

    Specific

    In the Admin panel (/admin), the CompanyResource table view gains a bulk action called "Assign User". When one or more companies are selected and the action is triggered, a modal opens with a searchable select of all User records. On confirmation, the selected user is attached to every selected company via the existing company_user pivot table.

    Measurable

    • Selecting 2+ companies and triggering the bulk action opens a modal with a User select.
    • After confirmation, a company_user row exists for the selected user in each selected company.
    • Already-attached users are not duplicated (use syncWithoutDetaching or attach with existence check).
    • A Filament success notification confirms how many companies were updated.

    Achievable

    1. Verify company_user pivot table and Company::users() / User::companies() BelongsToMany relations exist.
    2. Create AssignUserBulkAction Filament bulk action class.
    3. Register the bulk action on CompanyResource table.

    Relevant

    Platform admins frequently need to grant a support or billing user access to a portfolio of company accounts simultaneously. This bulk action eliminates the need to open each company individually.

    Time-bound

    Sprint 6.

  9. added a commit that references this issue on Sep 18, 2026
    a903606
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

refinedRefined with SMART plan / test suggestions

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions