Repository navigation
[Settings]: Company panel — assign Email Templates #239
Copy link
Copy link
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 assign Email Templates to that single company
Specific
Within the Company panel (/{tenant}), add an action (e.g. on the Settings page or as a dedicated relation manager / select field) that allows the customer_admin to choose a default EmailTemplate for their company. The selected template is stored on the company record (e.g. companies.default_email_template_id FK column) or via the company_email_template pivot with a is_default flag.
Measurable
- A
customer_admincan open the Settings page (or Email Template assignment page) in the company panel. - A select field shows all available email templates for the company.
- Saving the form persists the chosen template association.
- The association is retrievable via
$company->defaultEmailTemplate.
Achievable
- Add
default_email_template_idcolumn (nullable FK) tocompaniestable via migration —Modules/Core/Database/Migrations/ - Add
defaultEmailTemplate()BelongsTo onCompanymodel —Modules/Core/Models/Company.php - Add a
Selectfield fordefault_email_template_idon the company Settings schema —Modules/Core/Filament/Company/Pages/Settings.php(or create this page) - Scope the select options to templates available to this company.
- Protect the field / page with a
customer_adminrole check.
Relevant
Companies send invoices and quotes by email. Letting a customer_admin choose the default email template (subject line, greeting, footer) for outbound mail ensures brand consistency without requiring admin intervention on each document.
Time-bound
Sprint 6.
Arrange · Act · Assert
// Modules/Core/Tests/Feature/Company/CompanyEmailTemplateAssignmentTest.php
#[Test]
public function it_saves_default_email_template_for_company(): void
{
/* Arrange */
$template = EmailTemplate::factory()->for($this->company)->create();
/* Act */
$response = $this->testLivewire(CompanySettings::class)
->fillForm(['default_email_template_id' => $template->id])
->call('save');
/* Assert */
$response->assertHasNoErrors();
$this->assertDatabaseHas('companies', [
'id' => $this->company->id,
'default_email_template_id' => $template->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
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
Enable admins to assign email templates to companies through the Admin panel's Company management interface. This implementation adds a many-to-many relationship between companies and email templates, preserving existing ownership while allowing templates to be shared across companies. Companies will be able to access their own templates, system-level templates, and templates explicitly assigned to them.
Observations
This is a modular Laravel application with Filament admin panels. The Core module manages companies, users, and email templates. The application uses a multi-tenant architecture with three Filament panels (Admin, Company, User), where the Company panel provides tenant-scoped access. Email templates are currently company-owned resources stored in the
email_templatestable with acompany_idforeign key. The CompanyResource in the Admin panel currently has no relationship managers but uses delegated form/table schemas. The ReportBuilder module demonstrates a pattern for system-level templates using anis_systemboolean flag.Assumptions
Assumption 1: Template Availability Scope
Options Considered:
Chosen Option: 2
Rationale: This provides maximum flexibility while following the established
is_systempattern from ReportBuilder, allowing admins to share both system templates and company-specific templates across companies.Assumption 2: Template Ownership and Assignment Relationship
Options Considered:
company_idfor ownershipcompany_idand make all templates use only many-to-many relationshipsChosen Option: 1
Rationale: Preserve the existing
company_idfield to maintain ownership and add a many-to-many pivot table for assignments. This maintains backward compatibility and clearly distinguishes ownership from access.Assumption 3: Admin UI Location for Template Assignment
Options Considered:
Chosen Option: 1
Rationale: Follow Filament conventions by adding an EmailTemplatesRelationManager to CompanyResource, providing a clear, contextual interface for managing template assignments per company.
💡 User Tips
Regenerate the plan with different choices with
@coderabbitai <feedback>.Implementation Steps
Phase 1: Database Schema and Model Relationships
Add support for template assignment relationships while preserving existing company ownership structure.
Task 1: Add is_system Flag to Email Templates
Add capability to mark templates as system-level templates that can be shared across companies.
Modules/Core/Database/Migrations/to addis_systemboolean column toemail_templatestable (default false)Modules/Core/Models/EmailTemplate.phpto castis_systemas booleanisSystem()accessor method following the ReportBuilder patternTask 2: Create Template Assignment Pivot Table
Establish many-to-many relationship infrastructure for assigning templates to companies.
Modules/Core/Database/Migrations/forcompany_email_templatepivot table with columns:company_id,email_template_id,assigned_attimestamp['company_id', 'email_template_id']to prevent duplicate assignmentsTask 3: Add Assignment Relationships to Models
Connect companies and templates through the new many-to-many relationship.
Modules/Core/Models/EmailTemplate.phpto addassignedCompanies()BelongsToMany relationship usingcompany_email_templatepivotModules/Core/Models/Company.phpto addassignedEmailTemplates()BelongsToMany relationship usingcompany_email_templatepivotscopeAccessible()method to EmailTemplate model that returns templates owned by OR assigned to a given company usingwhere('company_id', $companyId)->orWhereHas('assignedCompanies')🤖 Prompt for AI agents
Phase 2: Template Management Service Layer
Extend service layer to handle template assignment operations while maintaining existing template creation functionality.
Extend EmailTemplateService for Assignments
Add template assignment business logic to the existing service.
Modules/Core/Services/EmailTemplateService.phpto addassignTemplatesToCompany(Company $company, array $templateIds)methodunassignTemplatesFromCompany(Company $company, array $templateIds)methodgetAccessibleTemplates(Company $company)method that retrieves both owned and assigned templates using thescopeAccessible()scope🤖 Prompt for AI agents
Phase 3: Admin Panel UI for Template Assignment
Implement Filament relationship manager interface in the Admin panel's Company management area.
Task 1: Create Email Templates Relationship Manager
Build Filament relationship manager for assigning templates to companies.
EmailTemplatesRelationManager.phpinModules/Core/Filament/Admin/Resources/Companies/RelationManagers/Task 2: Register Relationship Manager on CompanyResource
Connect the new relationship manager to the Company edit interface.
Modules/Core/Filament/Admin/Resources/Companies/CompanyResource.phpto addEmailTemplatesRelationManager::classto thegetRelations()arrayTask 3: Update Template Display to Show Assignment Status
Enhance template visibility to indicate ownership vs assignment.
Modules/Core/Filament/Admin/Resources/EmailTemplates/Schemas/EmailTemplatesTable.phpto add badge column showing "Owned", "System", or "Assigned" status🤖 Prompt for AI agents
Phase 4: Query Integration and Template Selection
Update existing template retrieval logic to include assigned templates alongside owned templates.
Task 1: Update Template Query Scopes
Ensure all template queries respect the new assignment relationships.
Modules/Core/Services/EmailTemplateService.phpmethods that retrieve templates to usescopeAccessible()instead of justscopeForCompany()Task 2: Update Template Selection Fields
Populate template selection dropdowns with accessible templates.
Modules/Core/Filament/Admin/Pages/Settings.phpto useEmailTemplate::accessible($company)->pluck('title', 'id')pattern🤖 Prompt for AI agents
Phase 5: System Template Seeding and Migration
Initialize system templates and migrate existing templates appropriately.
Task 1: Create System Template Seeder
Establish default system templates available to all companies.
SystemEmailTemplatesSeeder.phpinModules/Core/Database/Seeders/that creates system templates withis_system => trueandcompany_id => nullor a designated system company IDEmailTemplatesSeeder.phpbut mark templates as system templatesdatabase/seeders/DatabaseSeeder.phpwithin theseedGlobal()methodTask 2: Data Migration for Existing Templates
Ensure existing company templates remain functional.
Modules/Core/Database/Migrations/to setis_system => falsefor all existing templates (if not already handled by column default)company_idvalues as all current templates remain company-owned🤖 Prompt for AI agents
Phase 6: Testing Infrastructure
Implement comprehensive test coverage following AAA pattern for all template assignment scenarios.
Task 1: Model and Service Tests
Test template assignment business logic and model relationships.
EmailTemplateAssignmentTest.phpinModules/Core/Tests/Unit/covering:EmailTemplateServiceTest.phpinModules/Core/Tests/Unit/covering:Task 2: Filament Relationship Manager Tests
Test admin UI interactions for template assignment.
EmailTemplatesRelationManagerTest.phpinModules/Core/Tests/Feature/Filament/covering:Task 3: Query Integration Tests
Test template retrieval in various contexts.
EmailTemplateAccessTest.phpinModules/Core/Tests/Feature/covering:🤖 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!
[-]As an Admin, in the company Panel I want to be able to assign Email Templates to that single company[/-][+][Settings]: Company panel — assign Email Templates[/+]nielsdrost7 commentedon Jul 24, 2026
SMART Plan — Company panel — assign Email Templates
Specific
Within the Company panel Settings page, add multi-select fields (or a table) to assign Email Templates to the company for different lifecycle states: invoice sent, invoice paid, invoice overdue, quote sent, quote accepted. Templates are populated from EmailTemplate records scoped to the company. Only assigned templates appear in invoice/quote email form dropdowns.
Measurable
Achievable
Company::emailTemplates()as a BelongsToMany if not already present.Relevant
Template-heavy companies want to curate which templates each business unit can use, avoiding template pollution and accidental sends from wrong templates.
Time-bound
Sprint 6.
feat(InvoicePlane#239): wire up default email template selects on the…
nielsdrost7 commentedon Jul 24, 2026
Implemented on
feature/235-243-company-settings-cluster.CompanySettings.php's Invoices/Quotes tabs already had stubbedSelectfields for this (invoice_email_template,invoice_paid_email_template,invoice_overdue_email_template,quote_email_template) with emptyoptions([])— wired them toEmailTemplate::query()->where('company_id', $this->getCompanyId())->pluck('title', 'id'), matching the pattern already used for the invoice-numbering and tax-rate defaults. Persisted via the existingSettingkey/value mechanism (theSetting::KEY_*constants andallKeys()entries already existed). Test:CompanySettingsTest::it_offers_and_persists_default_email_templates_scoped_to_the_companyproves both the per-company scoping and persistence for all four keys.feat(InvoicePlane#239): wire up default email template selects on the…