since3-portal/lib/supabase/migrations/20260930120000_product_checks.sql
2026-09-29 15:20:50 +02:00

51 lines
1.8 KiB
SQL

-- Erreichbarkeitsprüfungen für Produkte (manuell per Button + beim Seitenaufruf)
create table public.product_checks (
id bigint generated always as identity primary key,
product_id uuid not null references public.client_products(id) on delete cascade,
client_id uuid not null references public.clients(id) on delete cascade,
checked_at timestamptz not null default now(),
ok boolean not null,
status_code int,
response_ms int,
error text
);
create index on public.product_checks (product_id, checked_at desc);
-- Lesen: Admin alles, Client nur eigene. Schreiben bewusst ohne Policy:
-- Ergebnisse schreibt nur der Server (Service Role), damit Clients ihre Uptime nicht fälschen können.
alter table public.product_checks enable row level security;
create policy admin_select on public.product_checks for select to authenticated
using ((select public.is_admin()));
create policy client_select on public.product_checks for select to authenticated
using (client_id = (select public.current_client_id()));
-- Letzte Prüfung + Uptime der letzten 30 Tage je Produkt
create view public.product_check_summary with (security_invoker = true) as
select
p.id as product_id,
last.checked_at,
last.ok,
last.status_code,
last.response_ms,
last.error,
stats.checks_30d,
stats.uptime_30d
from public.client_products p
left join lateral (
select c.checked_at, c.ok, c.status_code, c.response_ms, c.error
from public.product_checks c
where c.product_id = p.id
order by c.checked_at desc
limit 1
) last on true
left join lateral (
select
count(*)::int as checks_30d,
round(100.0 * count(*) filter (where c.ok) / nullif(count(*), 0), 2) as uptime_30d
from public.product_checks c
where c.product_id = p.id
and c.checked_at > now() - interval '30 days'
) stats on true;