-- REPORTE MENSUAL AL SENIAT (2026-07-28)
-- Obligacion de la imprenta digital: remitir la informacion de los documentos
-- del mes dentro de los 10 dias continuos siguientes (000102, art. 29). No
-- cumplirlo dos periodos en un año es causal de revocatoria (art. 34).
--
-- ⚠ El FORMATO oficial no esta publicado: se lo entregan a uno cuando lo
-- autorizan. Esto arma la relacion con lo que cualquier version va a pedir
-- (emisor, tipo, numero, numero de control, fecha, base, impuesto y total), en
-- un archivo plano facil de convertir. Cuando llegue el formato definitivo se
-- ajusta SOLO la funcion de armado, no el resto del sistema.
begin;

-- Deja constancia de cada envio: cuando se genero, cuantos documentos llevaba
-- y quien lo mando. Solo se agrega, nunca se edita.
create table if not exists fiscal.envios_mensuales (
  id uuid primary key default gen_random_uuid(),
  emisor_id uuid not null references fiscal.emisores(id) on delete restrict,
  periodo date not null,
  documentos integer not null,
  base_bs numeric(16,2) not null,
  iva_bs numeric(16,2) not null,
  total_bs numeric(16,2) not null,
  enviado_en timestamptz not null default now(),
  enviado_por text,
  nota text,
  unique (emisor_id, periodo, enviado_en)
);

create index if not exists envios_mensuales_emisor on fiscal.envios_mensuales (emisor_id, periodo desc);

revoke all on table fiscal.envios_mensuales from anon, authenticated;

-- La relacion de documentos de un mes, para armar el archivo.
create or replace function fiscal.relacion_mensual(p_rif text, p_anio int, p_mes int)
returns table(
  rif_emisor text,
  razon_social text,
  serie text,
  tipo text,
  numero_documento bigint,
  numero_control bigint,
  fecha_emision timestamptz,
  base_bs numeric,
  iva_bs numeric,
  total_bs numeric
)
language sql
stable
security definer
set search_path to 'fiscal', 'public'
as $fn$
  select e.rif, e.razon_social, d.serie, d.tipo, d.numero_documento, d.numero_control,
         d.fecha_emision, d.base_bs, d.iva_bs, d.total_bs
    from fiscal.documentos d
    join fiscal.emisores e on e.id = d.emisor_id
   where e.rif = public.fn_rif_normalizado(p_rif)
     and d.fecha_emision >= make_date(p_anio, p_mes, 1)
     and d.fecha_emision < (make_date(p_anio, p_mes, 1) + interval '1 month')
   order by d.numero_control;
$fn$;

-- El resumen del periodo: lo que va en la cabecera del envio.
create or replace function fiscal.resumen_mensual(p_rif text, p_anio int, p_mes int)
returns table(
  documentos integer,
  desde_control bigint,
  hasta_control bigint,
  base_bs numeric,
  iva_bs numeric,
  total_bs numeric,
  ya_enviado boolean
)
language sql
stable
security definer
set search_path to 'fiscal', 'public'
as $fn$
  with r as (
    select * from fiscal.relacion_mensual(p_rif, p_anio, p_mes)
  )
  select count(*)::int,
         min(numero_control),
         max(numero_control),
         coalesce(round(sum(base_bs), 2), 0),
         coalesce(round(sum(iva_bs), 2), 0),
         coalesce(round(sum(total_bs), 2), 0),
         exists (
           select 1 from fiscal.envios_mensuales em
             join fiscal.emisores e on e.id = em.emisor_id
            where e.rif = public.fn_rif_normalizado(p_rif)
              and em.periodo = make_date(p_anio, p_mes, 1)
         )
    from r;
$fn$;

-- Deja constancia de que el periodo se remitio.
create or replace function fiscal.marcar_enviado(p_rif text, p_anio int, p_mes int, p_quien text, p_nota text default null)
returns uuid
language plpgsql
security definer
set search_path to 'fiscal', 'public'
as $fn$
declare
  v_emisor uuid;
  v_res record;
  v_id uuid;
begin
  select id into v_emisor from fiscal.emisores where rif = public.fn_rif_normalizado(p_rif);
  if v_emisor is null then raise exception 'Ese RIF no esta registrado como emisor'; end if;

  select * into v_res from fiscal.resumen_mensual(p_rif, p_anio, p_mes);
  if v_res.documentos = 0 then
    raise exception 'No hay documentos en ese periodo';
  end if;

  insert into fiscal.envios_mensuales (emisor_id, periodo, documentos, base_bs, iva_bs, total_bs, enviado_por, nota)
    values (v_emisor, make_date(p_anio, p_mes, 1), v_res.documentos, v_res.base_bs, v_res.iva_bs, v_res.total_bs, p_quien, p_nota)
  returning id into v_id;
  return v_id;
end;
$fn$;

commit;
