Skip to content

[Settings]: Quotes — Quote Template #262

Closed

Description

@nielsdrost7

SMART Plan — Company Panel Quote Template Settings

Specific

Four per-company fields in the Quotes → Templates section of the Company Settings page:

Setting Type Purpose
Default PDF Template Select (pdf_template) Template for standard quote PDFs
Default Public Template Select (public_template) Guest-facing URL template for quote approval
Default Email Template Select (email_template) Email body when sending quotes to prospects
Quote PDF Footer Textarea Static HTML/text appended to all quote PDFs

Measurable

  • All four fields appear in the Quotes → Templates tab of CompanySettings
  • Each saves to settings keyed as quote_template_pdf_default, quote_template_public_default, quote_template_email_default, quote_pdf_footer
  • QuotePdfService and QuoteEmailService resolve the active template from these keys

Achievable

  1. Add four fields to CompanySettings under the Quotes > Templates tab
  2. Populate template select options from EmailTemplate::forCompany($company)->pluck('name', 'id')
  3. In QuotePdfService and QuoteEmailService, resolve template from the relevant setting key

Relevant

Gives companies control over quote presentation and email copy without touching code — mirrors the equivalent invoice template settings.

Time-bound

Sprint 6.


Arrange · Act · Assert

// Modules/Core/Tests/Feature/CompanySettingsTest.php

#[Test]
public function it_saves_quote_template_settings(): void
{
    /* Arrange */
    $emailTemplate = EmailTemplate::factory()->for($this->company)->create();
    $page = Livewire::actingAs($this->user)
        ->test(\Modules\Core\Filament\Company\Pages\CompanySettings::class);

    /* Act */
    $page->set('data.quote_template_email_default', $emailTemplate->id)
         ->set('data.quote_pdf_footer', 'Valid for 30 days.')
         ->call('save');

    /* Assert */
    $page->assertSuccessful();
    $this->assertDatabaseHas('settings', [
        'company_id' => $this->company->id,
        'key'        => 'quote_template_email_default',
        'value'      => (string) $emailTemplate->id,
    ]);
    $this->assertDatabaseHas('settings', [
        'company_id' => $this->company->id,
        'key'        => 'quote_pdf_footer',
        'value'      => 'Valid for 30 days.',
    ]);
}

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. changed the title [-]As an admin in the Company Panel, in the Quote Templates Settings (Quotes Tab, Per Company!), I want to be able to set:[/-] [+][Settings]: Quotes — Quote Template[/+] on Jun 13, 2026
  4. nielsdrost7 commented on Jul 24, 2026

    @nielsdrost7
    CollaboratorAuthor

    SMART Plan — Quote settings per-company: Template selection and footer

    Context/Epic: Settings

    Well-structured. A couple of notes:

    1. Infrastructure: Modules/Core/Filament/Company/Pages/CompanySettings.php doesn't exist yet. This batch of 8 settings issues ([Settings]: Invoices — Client Portal & Public Links #259–266) will scaffold it. Create a Quotes → Templates tab section as described in your plan.

    2. Service integration: You mentioned QuotePdfService and QuoteEmailService should resolve templates from these settings. Make sure:

      • Both services read from the correct setting keys at runtime (not at boot time, so settings can change per-request).
      • They handle gracefully when a stored template ID points to a deleted EmailTemplate (fallback to company default or skip personalization).
    3. Footer scope: The "Quote PDF Footer" is stored as a textarea. Make sure the PDF renderer escapes/sanitizes it to prevent injection (if it's meant to be literal text) or properly handles HTML if that's intentional.

    4. Null handling: What if no templates are set? Queries like EmailTemplate::forCompany()->pluck('name', 'id') should return empty collections gracefully, and services should have fallback behavior.

    Ready to implement — four related fields, good measurable tests.

  5. nielsdrost7 commented on Jul 24, 2026

    @nielsdrost7
    CollaboratorAuthor

    Correction: an unmerged local branch, settings-cluster-2026-07-19, already implements this via a new Modules/Core/Filament/Company/Pages/CompanySettings.php page (490 lines) + CompanySettingsTest.php, covering mail send method/from-address, default invoice/quote tax rates, quote PDF template/public/email templates, quote footer, quote validity days, invoice/quote PDF password + mark-as-sent toggles, and invoice default footer. The SMART Plan comment above was posted in error by an automated grooming pass that didn't check non-issue-numbered branch names. Please check that branch before implementing this from scratch — it may just need finishing/rebasing rather than a fresh implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    refinedRefined with SMART plan / test suggestions

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions