You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Parent epic for all company-panel settings: general, amounts, dashboard, invoices (PDF/QR/email/template), quotes (PDF/template), taxes, email, system settings, and admin-panel global settings assignment.
This is an epic/tracking issue, not a single feature — it aggregates the sub-issues below. The Measurable section tracks sub-issue completion rather than fabricating tests for the epic itself; each sub-issue gets its own SMART Plan when it's processed individually.
Specific
Track delivery of all company-panel settings: general, amounts, dashboard, invoices (PDF/QR/email/template), quotes (PDF/template), taxes, email, system settings, and admin-panel global settings assignment. Current state, and this is the central finding for this whole epic: there is no company-panel settings page at all. The only Settings page in the codebase is Modules\Core\Filament\Admin\Pages\Settings.php, on the admin panel, gated by Permission::MANAGE_SETTINGS. It already has an extensive, well-organized tabbed form covering almost everything this epic describes — General, Amount, Dashboard, Interface, System, Invoices (with PDF/QR/template/email sub-sections), Quotes (with PDF/template sub-sections), Taxes, Email/SMTP, Online Payment (Stripe/PayPal placeholders), Projects, and Updates. But it is not wired to persist anything: mount() seeds $this->settings from hardcoded defaults, and submit() explicitly does nothing beyond re-reading the form state — // Here you would save settings to database or config / For now, just keep them in memory. The underlying Modules\Core\Models\Setting key-value table also has no company_id column at all, so even if submit() were wired up, it would store settings globally across every company, not per-tenant — which conflicts with this epic's premise of "company-panel settings."
Measurable
A company-panel Settings page exists at all (distinct from the admin one) — not started; UserPanelProvider and CompanyPanelProvider have no settings page registered.
Settings persist to the database — not started; Settings::submit() on the existing (admin) page is a no-op today.
Settings are company-scoped — not started; the settings table has no company_id column, so the current storage mechanism can't support per-company values even once persistence is wired up.
General / Amounts / Dashboard / Interface / System tabs — form fields already exist (on the wrong panel, unwired) and can likely be ported largely as-is once the above three are resolved.
Invoices (PDF/QR/email/template) tab — form fields already exist (same caveat).
Quotes (PDF/template) tab — form fields already exist (same caveat).
Taxes tab — form fields already exist (same caveat).
Email/SMTP tab — form fields already exist (same caveat).
Admin-panel global settings assignment — partially exists in spirit (the admin Settings page itself), but its relationship to per-company settings (which should win, does one override the other) is undefined.
Definition of done for this epic: a company-panel settings page exists, is company-scoped, actually persists to the database, and each functional area above round-trips correctly with test coverage in Modules/Core/Tests/Feature/.
Achievable
Decide the storage model first — before porting any of the existing (unwired) form tabs, resolve whether settings gets a company_id column added, or a new company-scoped settings table/model is introduced. This blocks every other item in this epic.
Build a company-panel Settings page under Modules/Core/Filament/Company/Pages/ — the existing admin page's getFormSchema() tab structure is a solid template to copy from, but it needs a real submit() that persists via whatever storage model is chosen in step 1.
Once persistence + company-scoping exist, port the tabs one at a time (General → Amounts → Invoices → Quotes → Taxes → Email), since they're already fully designed forms just sitting on the wrong panel.
Decide the relationship between the admin-panel Settings page (global) and the new company-panel one (per-tenant) — e.g. do company settings override global defaults, or are they entirely separate.
Tests in Modules/Core/Tests/Feature/ for persistence, company scoping, and each tab's round-trip.
Relevant
Every sub-issue in this epic is currently blocked on the same two facts: no company-panel settings page exists, and the one settings page that does exist doesn't save anything. Fixing the storage/persistence question once unblocks the entire epic at once rather than piecemeal.
Time-bound
No fixed date — epic closes when its sub-issues close. Re-review at each sprint boundary. Recommend treating "company-scoped, persisting settings page" as its own Sprint 6 spike before scheduling the individual tabs.
Activity
22 remaining items
nielsdrost7 commentedon Jul 16, 2026
SMART Plan — Company Settings epic status
Specific
Track delivery of all company-panel settings: general, amounts, dashboard, invoices (PDF/QR/email/template), quotes (PDF/template), taxes, email, system settings, and admin-panel global settings assignment. Current state, and this is the central finding for this whole epic: there is no company-panel settings page at all. The only
Settingspage in the codebase isModules\Core\Filament\Admin\Pages\Settings.php, on the admin panel, gated byPermission::MANAGE_SETTINGS. It already has an extensive, well-organized tabbed form covering almost everything this epic describes — General, Amount, Dashboard, Interface, System, Invoices (with PDF/QR/template/email sub-sections), Quotes (with PDF/template sub-sections), Taxes, Email/SMTP, Online Payment (Stripe/PayPal placeholders), Projects, and Updates. But it is not wired to persist anything:mount()seeds$this->settingsfrom hardcoded defaults, andsubmit()explicitly does nothing beyond re-reading the form state —// Here you would save settings to database or config / For now, just keep them in memory. The underlyingModules\Core\Models\Settingkey-value table also has nocompany_idcolumn at all, so even ifsubmit()were wired up, it would store settings globally across every company, not per-tenant — which conflicts with this epic's premise of "company-panel settings."Measurable
Settingspage exists at all (distinct from the admin one) — not started;UserPanelProviderandCompanyPanelProviderhave no settings page registered.Settings::submit()on the existing (admin) page is a no-op today.settingstable has nocompany_idcolumn, so the current storage mechanism can't support per-company values even once persistence is wired up.Settingspage itself), but its relationship to per-company settings (which should win, does one override the other) is undefined.Definition of done for this epic: a company-panel settings page exists, is company-scoped, actually persists to the database, and each functional area above round-trips correctly with test coverage in
Modules/Core/Tests/Feature/.Achievable
settingsgets acompany_idcolumn added, or a new company-scoped settings table/model is introduced. This blocks every other item in this epic.Settingspage underModules/Core/Filament/Company/Pages/— the existing admin page'sgetFormSchema()tab structure is a solid template to copy from, but it needs a realsubmit()that persists via whatever storage model is chosen in step 1.Settingspage (global) and the new company-panel one (per-tenant) — e.g. do company settings override global defaults, or are they entirely separate.Modules/Core/Tests/Feature/for persistence, company scoping, and each tab's round-trip.Relevant
Every sub-issue in this epic is currently blocked on the same two facts: no company-panel settings page exists, and the one settings page that does exist doesn't save anything. Fixing the storage/persistence question once unblocks the entire epic at once rather than piecemeal.
Time-bound
No fixed date — epic closes when its sub-issues close. Re-review at each sprint boundary. Recommend treating "company-scoped, persisting settings page" as its own Sprint 6 spike before scheduling the individual tabs.