caterium-app/ops/sql/SUPABASE-V17.6.8-DEVELOPER-CONSOLE-UX.sql
pavlov346346-source 4ba730990b
Caterium v17.6.8 — Developer Console UX and error fixes
* Add v17.6.8 Developer Console UX and race fixes

* Add Developer Console numbering delete and grouped error RPCs

* Add one-time v17.6.8 release preparation workflow

* Prepare Caterium v17.6.8 Developer Console UX

* Remove one-time v17.6.8 release workflow

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-09-08 07:58:54 +03:00

237 lines
6.9 KiB
PL/PgSQL

-- 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;