feat: actualizar Tablero CDC con administracion de listas
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
-- =========================================================
|
||||
-- TABLERO CDC - TIEMPO DEDICADO POR PROYECTO
|
||||
-- Ejecutar una sola vez en Supabase SQL Editor antes de desplegar
|
||||
-- la versión que incluye el botón "Tiempo".
|
||||
--
|
||||
-- Objetivo:
|
||||
-- - Registrar tiempo dedicado a un proyecto.
|
||||
-- - Desglosar ese tiempo por país y por tarea.
|
||||
-- - Conservar fecha, notas y quién registró cada entrada.
|
||||
-- - No modifica tablero_cdc_projects ni altera tarifarios, montos,
|
||||
-- Google Sheets, n8n o datos históricos existentes.
|
||||
-- =========================================================
|
||||
|
||||
begin;
|
||||
|
||||
create table if not exists public.tablero_cdc_project_time_entries (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
project_id uuid not null references public.tablero_cdc_projects(id) on delete cascade,
|
||||
country text not null,
|
||||
task_name text not null,
|
||||
duration_minutes integer not null check (duration_minutes > 0),
|
||||
work_date date not null default current_date,
|
||||
notes text not null default '',
|
||||
created_by uuid references auth.users(id),
|
||||
created_by_email text,
|
||||
created_by_name text,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now(),
|
||||
constraint tablero_cdc_project_time_entries_country_not_blank
|
||||
check (length(trim(country)) > 0),
|
||||
constraint tablero_cdc_project_time_entries_task_not_blank
|
||||
check (length(trim(task_name)) > 0)
|
||||
);
|
||||
|
||||
comment on table public.tablero_cdc_project_time_entries is
|
||||
'Registros de tiempo dedicado a proyectos CDC, desglosados por país y tarea.';
|
||||
|
||||
comment on column public.tablero_cdc_project_time_entries.duration_minutes is
|
||||
'Duración exacta almacenada en minutos para evitar errores de redondeo.';
|
||||
|
||||
create index if not exists tablero_cdc_project_time_entries_project_date_idx
|
||||
on public.tablero_cdc_project_time_entries(project_id, work_date desc, created_at desc);
|
||||
|
||||
create index if not exists tablero_cdc_project_time_entries_project_country_idx
|
||||
on public.tablero_cdc_project_time_entries(project_id, country);
|
||||
|
||||
create index if not exists tablero_cdc_project_time_entries_project_task_idx
|
||||
on public.tablero_cdc_project_time_entries(project_id, task_name);
|
||||
|
||||
create or replace function public.set_tablero_cdc_project_time_entries_audit()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
security invoker
|
||||
set search_path = public
|
||||
as $$
|
||||
begin
|
||||
new.country = trim(new.country);
|
||||
new.task_name = trim(new.task_name);
|
||||
new.notes = coalesce(trim(new.notes), '');
|
||||
new.updated_at = now();
|
||||
|
||||
if tg_op = 'INSERT' then
|
||||
-- La identidad se toma de la sesión autenticada, no de valores enviados por el cliente.
|
||||
new.created_by = auth.uid();
|
||||
new.created_by_email = coalesce(
|
||||
nullif(lower(trim(coalesce(auth.jwt() ->> 'email', ''))), ''),
|
||||
nullif(lower(trim(coalesce(new.created_by_email, ''))), '')
|
||||
);
|
||||
new.created_by_name = coalesce(
|
||||
nullif(trim(coalesce(auth.jwt() -> 'user_metadata' ->> 'full_name', '')), ''),
|
||||
nullif(trim(coalesce(auth.jwt() -> 'user_metadata' ->> 'name', '')), ''),
|
||||
nullif(trim(coalesce(new.created_by_name, '')), ''),
|
||||
new.created_by_email,
|
||||
'Usuario CDC'
|
||||
);
|
||||
end if;
|
||||
|
||||
return new;
|
||||
end;
|
||||
$$;
|
||||
|
||||
drop trigger if exists trg_tablero_cdc_project_time_entries_audit
|
||||
on public.tablero_cdc_project_time_entries;
|
||||
|
||||
create trigger trg_tablero_cdc_project_time_entries_audit
|
||||
before insert or update on public.tablero_cdc_project_time_entries
|
||||
for each row
|
||||
execute function public.set_tablero_cdc_project_time_entries_audit();
|
||||
|
||||
alter table public.tablero_cdc_project_time_entries enable row level security;
|
||||
|
||||
drop policy if exists "tablero_cdc_project_time_entries_select_allowed" on public.tablero_cdc_project_time_entries;
|
||||
drop policy if exists "tablero_cdc_project_time_entries_insert_allowed" on public.tablero_cdc_project_time_entries;
|
||||
drop policy if exists "tablero_cdc_project_time_entries_update_allowed" on public.tablero_cdc_project_time_entries;
|
||||
drop policy if exists "tablero_cdc_project_time_entries_delete_allowed" on public.tablero_cdc_project_time_entries;
|
||||
|
||||
-- Se valida contra la misma tabla central de acceso del Tablero CDC.
|
||||
-- Así, una sesión Google autenticada pero NO autorizada para el Tablero
|
||||
-- tampoco puede leer o escribir tiempos mediante la API de Supabase.
|
||||
create policy "tablero_cdc_project_time_entries_select_allowed"
|
||||
on public.tablero_cdc_project_time_entries
|
||||
for select
|
||||
to authenticated
|
||||
using (
|
||||
exists (
|
||||
select 1
|
||||
from public.tablero_cdc_allowed_users u
|
||||
where lower(trim(u.email)) = lower(trim(coalesce(auth.jwt() ->> 'email', '')))
|
||||
and u.is_active = true
|
||||
)
|
||||
);
|
||||
|
||||
create policy "tablero_cdc_project_time_entries_insert_allowed"
|
||||
on public.tablero_cdc_project_time_entries
|
||||
for insert
|
||||
to authenticated
|
||||
with check (
|
||||
exists (
|
||||
select 1
|
||||
from public.tablero_cdc_allowed_users u
|
||||
where lower(trim(u.email)) = lower(trim(coalesce(auth.jwt() ->> 'email', '')))
|
||||
and u.is_active = true
|
||||
)
|
||||
);
|
||||
|
||||
create policy "tablero_cdc_project_time_entries_update_allowed"
|
||||
on public.tablero_cdc_project_time_entries
|
||||
for update
|
||||
to authenticated
|
||||
using (
|
||||
exists (
|
||||
select 1
|
||||
from public.tablero_cdc_allowed_users u
|
||||
where lower(trim(u.email)) = lower(trim(coalesce(auth.jwt() ->> 'email', '')))
|
||||
and u.is_active = true
|
||||
)
|
||||
)
|
||||
with check (
|
||||
exists (
|
||||
select 1
|
||||
from public.tablero_cdc_allowed_users u
|
||||
where lower(trim(u.email)) = lower(trim(coalesce(auth.jwt() ->> 'email', '')))
|
||||
and u.is_active = true
|
||||
)
|
||||
);
|
||||
|
||||
create policy "tablero_cdc_project_time_entries_delete_allowed"
|
||||
on public.tablero_cdc_project_time_entries
|
||||
for delete
|
||||
to authenticated
|
||||
using (
|
||||
exists (
|
||||
select 1
|
||||
from public.tablero_cdc_allowed_users u
|
||||
where lower(trim(u.email)) = lower(trim(coalesce(auth.jwt() ->> 'email', '')))
|
||||
and u.is_active = true
|
||||
)
|
||||
);
|
||||
|
||||
grant select, insert, update, delete
|
||||
on public.tablero_cdc_project_time_entries
|
||||
to authenticated;
|
||||
|
||||
-- Realtime no es obligatorio para el funcionamiento, pero se habilita
|
||||
-- para que el módulo quede preparado para sincronización multiusuario.
|
||||
do $$
|
||||
begin
|
||||
if not exists (
|
||||
select 1
|
||||
from pg_publication_tables
|
||||
where pubname = 'supabase_realtime'
|
||||
and schemaname = 'public'
|
||||
and tablename = 'tablero_cdc_project_time_entries'
|
||||
) then
|
||||
alter publication supabase_realtime add table public.tablero_cdc_project_time_entries;
|
||||
end if;
|
||||
end $$;
|
||||
|
||||
commit;
|
||||
|
||||
-- =========================================================
|
||||
-- VERIFICACIÓN
|
||||
-- Debe devolver la tabla y 0 registros si todavía no se ha agregado tiempo.
|
||||
-- =========================================================
|
||||
select
|
||||
count(*) as registros_de_tiempo,
|
||||
coalesce(sum(duration_minutes), 0) as minutos_totales
|
||||
from public.tablero_cdc_project_time_entries;
|
||||
Reference in New Issue
Block a user