/* * ------------------------------------------------------- * Newsletter Schema * Phase 10: newsletters, recipients, templates, messages * ------------------------------------------------------- */ create type public.newsletter_status as enum('draft', 'scheduled', 'sending', 'sent', 'failed'); create table if not exists public.newsletter_templates ( id uuid primary key default gen_random_uuid(), account_id uuid not null references public.accounts(id) on delete cascade, name text not null, subject text not null, body_html text not null, body_text text, variables jsonb not null default '[]'::jsonb, created_at timestamptz not null default now(), updated_at timestamptz not null default now() ); create index ix_newsletter_templates_account on public.newsletter_templates(account_id); alter table public.newsletter_templates enable row level security; revoke all on public.newsletter_templates from authenticated, service_role; grant select, insert, update, delete on public.newsletter_templates to authenticated; grant all on public.newsletter_templates to service_role; create policy newsletter_templates_select on public.newsletter_templates for select to authenticated using (public.has_role_on_account(account_id)); create policy newsletter_templates_mutate on public.newsletter_templates for all to authenticated using (public.has_permission(auth.uid(), account_id, 'newsletter.send'::public.app_permissions)); create table if not exists public.newsletters ( id uuid primary key default gen_random_uuid(), account_id uuid not null references public.accounts(id) on delete cascade, template_id uuid references public.newsletter_templates(id) on delete set null, subject text not null, body_html text not null, body_text text, status public.newsletter_status not null default 'draft', scheduled_at timestamptz, sent_at timestamptz, total_recipients integer not null default 0, sent_count integer not null default 0, failed_count integer not null default 0, created_by uuid references auth.users(id) on delete set null, created_at timestamptz not null default now(), updated_at timestamptz not null default now() ); create index ix_newsletters_account on public.newsletters(account_id); alter table public.newsletters enable row level security; revoke all on public.newsletters from authenticated, service_role; grant select, insert, update, delete on public.newsletters to authenticated; grant all on public.newsletters to service_role; create policy newsletters_select on public.newsletters for select to authenticated using (public.has_role_on_account(account_id)); create policy newsletters_mutate on public.newsletters for all to authenticated using (public.has_permission(auth.uid(), account_id, 'newsletter.send'::public.app_permissions)); create table if not exists public.newsletter_recipients ( id uuid primary key default gen_random_uuid(), newsletter_id uuid not null references public.newsletters(id) on delete cascade, member_id uuid references public.members(id) on delete set null, email text not null, name text, status text not null default 'pending' check (status in ('pending', 'sent', 'failed', 'bounced')), sent_at timestamptz, error_message text ); create index ix_newsletter_recipients_newsletter on public.newsletter_recipients(newsletter_id); alter table public.newsletter_recipients enable row level security; revoke all on public.newsletter_recipients from authenticated, service_role; grant select, insert, update, delete on public.newsletter_recipients to authenticated; grant all on public.newsletter_recipients to service_role; create policy newsletter_recipients_select on public.newsletter_recipients for select to authenticated using (exists (select 1 from public.newsletters n where n.id = newsletter_recipients.newsletter_id and public.has_role_on_account(n.account_id))); create policy newsletter_recipients_mutate on public.newsletter_recipients for all to authenticated using (exists (select 1 from public.newsletters n where n.id = newsletter_recipients.newsletter_id and public.has_permission(auth.uid(), n.account_id, 'newsletter.send'::public.app_permissions)));