-- Caterium v17.6.8 Developer Console UX -- Persistent company numbers, safe company deletion and grouped production error journal. create sequence if not exists public.sun_workspace_company_number_seq; alter table public.sun_workspaces add column if not exists company_number bigint; with numbered as ( select id,row_number() over(order by created_at,id)::bigint as n from public.sun_workspaces where company_number is null ), existing as ( select coalesce(max(company_number),0)::bigint as max_n from public.sun_workspaces ) update public.sun_workspaces w set company_number = numbered.n + existing.max_n from numbered,existing where w.id=numbered.id and w.company_number is null; select setval( 'public.sun_workspace_company_number_seq', greatest(1,coalesce((select max(company_number) from public.sun_workspaces),0)), coalesce((select max(company_number) from public.sun_workspaces),0)>0 ); alter table public.sun_workspaces alter column company_number set default nextval('public.sun_workspace_company_number_seq'); update public.sun_workspaces set company_number=nextval('public.sun_workspace_company_number_seq') where company_number is null; alter table public.sun_workspaces alter column company_number set not null; create unique index if not exists sun_workspaces_company_number_uq on public.sun_workspaces(company_number); create or replace function public.sun_dev_list_companies_v1768() returns table( workspace_id uuid, workspace_name text, company_number bigint, created_at timestamptz, plan_id text, plan_name text, status text, access_mode text, trial_ends_at timestamptz, current_period_end timestamptz, grace_until timestamptz, member_count bigint, max_members integer, owner_email text, pending_owner_email text ) language plpgsql stable security definer set search_path='public','auth' as $$ begin perform public.sun_require_platform_admin_aal2(); return query select w.id, w.name, w.company_number, w.created_at, s.plan_id, p.name, s.status, public.sun_subscription_access_mode(w.id), s.trial_ends_at, s.current_period_end, s.grace_until, (select count(*) from public.sun_workspace_members m where m.workspace_id=w.id and m.is_active), p.max_members, (select u.email::text from public.sun_workspace_members m join auth.users u on u.id=m.user_id where m.workspace_id=w.id and m.role='admin' and m.is_active order by m.created_at asc limit 1), (select i.email from public.caterium_company_owner_invites i where i.workspace_id=w.id and i.used_at is null and i.expires_at>now() order by i.created_at desc limit 1) from public.sun_workspaces w left join public.sun_workspace_subscriptions s on s.workspace_id=w.id left join public.sun_plans p on p.id=s.plan_id order by w.company_number; end; $$; create or replace function public.sun_dev_delete_company_v1768( p_workspace uuid, p_confirm_name text ) returns jsonb language plpgsql security definer set search_path='public','auth' as $$ declare v_name text; v_number bigint; v_members bigint; v_orders bigint; v_clients bigint; v_catalog bigint; begin perform public.sun_require_platform_admin_aal2(); select w.name,w.company_number into v_name,v_number from public.sun_workspaces w where w.id=p_workspace for update; if v_name is null then raise exception 'Workspace not found'; end if; if trim(coalesce(p_confirm_name,'')) <> v_name then raise exception 'Company name confirmation mismatch'; end if; select count(*) into v_members from public.sun_workspace_members where workspace_id=p_workspace; select count(*) into v_orders from public.sun_v17_orders where workspace_id=p_workspace; select count(*) into v_clients from public.sun_v17_clients where workspace_id=p_workspace; select count(*) into v_catalog from public.sun_v17_catalog_items where workspace_id=p_workspace; perform public.sun_platform_log_event( 'company.delete', p_workspace, null, jsonb_build_object( 'company',v_name, 'company_number',v_number, 'members',v_members, 'orders',v_orders, 'clients',v_clients, 'catalog_items',v_catalog, 'auth_accounts_preserved',true ) ); delete from public.sun_workspaces where id=p_workspace; return jsonb_build_object( 'deleted',true, 'workspace_id',p_workspace, 'workspace_name',v_name, 'company_number',v_number, 'memberships_removed',v_members, 'auth_accounts_preserved',true ); end; $$; create or replace function public.sun_dev_error_groups_v1768( p_hours integer default 168, p_limit integer default 100 ) returns table( workspace_name text, app_version text, level text, message text, occurrences bigint, first_seen timestamptz, last_seen timestamptz, sample_stack text, source_url text ) language plpgsql stable security definer set search_path='public' as $$ declare v_hours integer:=greatest(1,least(coalesce(p_hours,168),720)); v_limit integer:=greatest(1,least(coalesce(p_limit,100),200)); begin perform public.sun_require_platform_admin_aal2(); return query with scoped as ( select e.*, w.name as company_name, nullif(e.context->>'url','') as event_url from public.sun_v17_error_events e left join public.sun_workspaces w on w.id=e.workspace_id where e.created_at >= now()-make_interval(hours=>v_hours) and coalesce(e.context->>'url','') !~* '^file:' ), grouped as ( select company_name, coalesce(app_version,'') as app_version, coalesce(level,'error') as level, coalesce(message,'Unknown error') as message, count(*)::bigint as occurrences, min(created_at) as first_seen, max(created_at) as last_seen from scoped group by company_name,coalesce(app_version,''),coalesce(level,'error'),coalesce(message,'Unknown error') ) select g.company_name, nullif(g.app_version,''), g.level, g.message, g.occurrences, g.first_seen, g.last_seen, s.stack, s.event_url from grouped g left join lateral ( select x.stack,x.event_url from scoped x where x.company_name is not distinct from g.company_name and coalesce(x.app_version,'')=g.app_version and coalesce(x.level,'error')=g.level and coalesce(x.message,'Unknown error')=g.message order by x.created_at desc limit 1 ) s on true order by g.last_seen desc limit v_limit; end; $$; revoke all on function public.sun_dev_list_companies_v1768() from public,anon; revoke all on function public.sun_dev_delete_company_v1768(uuid,text) from public,anon; revoke all on function public.sun_dev_error_groups_v1768(integer,integer) from public,anon; grant execute on function public.sun_dev_list_companies_v1768() to authenticated; grant execute on function public.sun_dev_delete_company_v1768(uuid,text) to authenticated; grant execute on function public.sun_dev_error_groups_v1768(integer,integer) to authenticated;