diff --git a/lib/api/schemas.ts b/lib/api/schemas.ts
index bb879f55..f8bcf836 100644
--- a/lib/api/schemas.ts
+++ b/lib/api/schemas.ts
@@ -400,6 +400,7 @@ export const UpdateSettingsSchema = z.object({
invoice_show_plusgiro: z.boolean().optional(),
invoice_show_logo: z.boolean().optional(),
invoice_show_company_name: z.boolean().optional(),
+ invoice_company_name_position: z.enum(['header', 'footer']).optional(),
invoice_late_fee_text: z.string().nullable().optional(),
invoice_credit_terms_text: z.string().nullable().optional(),
// AI agent flow
diff --git a/lib/invoices/pdf-template.tsx b/lib/invoices/pdf-template.tsx
index 7a966b92..ce7412da 100644
--- a/lib/invoices/pdf-template.tsx
+++ b/lib/invoices/pdf-template.tsx
@@ -377,9 +377,10 @@ export function InvoicePDF({ invoice, customer, items, company, originalInvoiceN
{company.logo_url && (company.invoice_show_logo ?? true) && (
)}
- {(company.invoice_show_company_name ?? true) && (
- {company.company_name}
- )}
+ {(company.invoice_show_company_name ?? true) &&
+ (company.invoice_company_name_position ?? 'header') === 'header' && (
+ {company.company_name}
+ )}
@@ -667,6 +668,10 @@ export function InvoicePDF({ invoice, customer, items, company, originalInvoiceN
{[
+ (company.invoice_show_company_name ?? true) &&
+ (company.invoice_company_name_position ?? 'header') === 'footer'
+ ? company.company_name
+ : null,
company.address_line1,
(company.postal_code || company.city) ? `${company.postal_code ?? ''} ${company.city ?? ''}`.trim() : null,
company.org_number ? `Org.nr: ${formatOrgNumber(company.org_number)}` : null,
diff --git a/supabase/migrations/20260513130000_invoice_company_name_position.sql b/supabase/migrations/20260513130000_invoice_company_name_position.sql
new file mode 100644
index 00000000..b628a713
--- /dev/null
+++ b/supabase/migrations/20260513130000_invoice_company_name_position.sql
@@ -0,0 +1,10 @@
+-- Add invoice_company_name_position to control whether the company name
+-- appears in the invoice PDF header (under the logo) or in the footer.
+-- Default 'header' preserves existing layout for all current users.
+
+ALTER TABLE public.company_settings
+ ADD COLUMN IF NOT EXISTS invoice_company_name_position text
+ NOT NULL DEFAULT 'header'
+ CHECK (invoice_company_name_position IN ('header', 'footer'));
+
+NOTIFY pgrst, 'reload schema';
diff --git a/supabase/migrations/20260513130001_backfill_vat_account_labels.sql b/supabase/migrations/20260513130001_backfill_vat_account_labels.sql
new file mode 100644
index 00000000..524d2b52
--- /dev/null
+++ b/supabase/migrations/20260513130001_backfill_vat_account_labels.sql
@@ -0,0 +1,90 @@
+-- Backfill: fix VAT account labels on companies that were seeded by the
+-- regressed seed_chart_of_accounts() between 2026-03-30 and 2026-05-13.
+--
+-- Companion to 20260513120000_fix_vat_seed_chart_of_accounts.sql. The earlier
+-- migration patched the seed function so new companies get correct labels.
+-- This one cleans up companies that were already created with the bad seed.
+--
+-- Safety notes:
+-- * Every WHERE clause matches the EXACT bad-seed name, so customers who
+-- have already manually renamed an account are left alone.
+-- * Orphan 2610 / 2612 rows are only deleted if no journal line references
+-- them. The engine never routes to 2610/2612, so this should be true for
+-- all bad-seed companies; the guard is defense in depth.
+-- * 2621 / 2631 are inserted only for companies that show the bad-seed
+-- fingerprint (a mislabelled 2611 carrying one of the two bad-seed names).
+-- plan_type is derived from that sibling 2611 row rather than hardcoded
+-- to 'k1', so any company that manually adjusted plan_type keeps it.
+
+BEGIN;
+
+-- 1. Rename mislabelled 2611 -> 25%
+UPDATE public.chart_of_accounts
+ SET account_name = 'Utgaende moms forsaljning inom Sverige, 25%',
+ updated_at = now()
+ WHERE account_number = '2611'
+ AND account_name IN ('Utgaende moms 12%', 'Utgående moms 12%');
+
+-- 2. Insert missing 2621 (12%) for bad-seed companies that lack it.
+-- Scoped to companies that had the bad-seed fingerprint on 2611
+-- (rename in step 1 above, or the orphan 2610/2612 pattern in step 4).
+INSERT INTO public.chart_of_accounts
+ (user_id, company_id, account_number, account_name, account_class,
+ account_group, account_type, normal_balance, plan_type, is_system_account)
+SELECT c.created_by,
+ c.id,
+ '2621',
+ 'Utgaende moms forsaljning inom Sverige, 12%',
+ 2, '26', 'liability', 'credit', sibling.plan_type, true
+ FROM public.companies c
+ JOIN public.chart_of_accounts sibling
+ ON sibling.company_id = c.id
+ AND sibling.account_number = '2611'
+ WHERE sibling.account_name = 'Utgaende moms forsaljning inom Sverige, 25%'
+ AND NOT EXISTS (
+ SELECT 1 FROM public.chart_of_accounts coa
+ WHERE coa.company_id = c.id
+ AND coa.account_number = '2621'
+ );
+
+-- 3. Insert missing 2631 (6%) for bad-seed companies that lack it.
+INSERT INTO public.chart_of_accounts
+ (user_id, company_id, account_number, account_name, account_class,
+ account_group, account_type, normal_balance, plan_type, is_system_account)
+SELECT c.created_by,
+ c.id,
+ '2631',
+ 'Utgaende moms forsaljning inom Sverige, 6%',
+ 2, '26', 'liability', 'credit', sibling.plan_type, true
+ FROM public.companies c
+ JOIN public.chart_of_accounts sibling
+ ON sibling.company_id = c.id
+ AND sibling.account_number = '2611'
+ WHERE sibling.account_name = 'Utgaende moms forsaljning inom Sverige, 25%'
+ AND NOT EXISTS (
+ SELECT 1 FROM public.chart_of_accounts coa
+ WHERE coa.company_id = c.id
+ AND coa.account_number = '2631'
+ );
+
+-- 4. Remove orphan 2610 / 2612 rows created by the bad seed.
+-- Only rows that (a) still carry the bad-seed name verbatim, and
+-- (b) have zero postings on journal_entry_lines are removed.
+DELETE FROM public.chart_of_accounts coa
+ WHERE coa.account_number IN ('2610', '2612')
+ AND coa.account_name IN (
+ 'Utgaende moms 25%', 'Utgående moms 25%',
+ 'Utgaende moms 6%', 'Utgående moms 6%'
+ )
+ AND coa.is_system_account = true
+ AND NOT EXISTS (
+ SELECT 1
+ FROM public.journal_entry_lines jel
+ JOIN public.journal_entries je ON je.id = jel.journal_entry_id
+ WHERE jel.account_number = coa.account_number
+ AND je.company_id = coa.company_id
+ );
+
+COMMIT;
+
+NOTIFY pgrst, 'reload schema';
diff --git a/tests/helpers.ts b/tests/helpers.ts
index d0df1376..8b00caac 100644
--- a/tests/helpers.ts
+++ b/tests/helpers.ts
@@ -532,6 +532,7 @@ export function makeCompanySettings(
invoice_show_plusgiro: true,
invoice_show_logo: true,
invoice_show_company_name: true,
+ invoice_company_name_position: 'header',
invoice_late_fee_text: null,
invoice_credit_terms_text: null,
logo_url: null,
diff --git a/types/index.ts b/types/index.ts
index 511bfc4d..4d6facce 100644
--- a/types/index.ts
+++ b/types/index.ts
@@ -241,6 +241,7 @@ export interface CompanySettings {
invoice_show_plusgiro: boolean
invoice_show_logo: boolean
invoice_show_company_name: boolean
+ invoice_company_name_position: 'header' | 'footer'
invoice_late_fee_text: string | null
invoice_credit_terms_text: string | null