-- ============================================= -- Módulo de Diezmos — Script SQL de migración -- Ejecutar contra la BD de desarrollo/producción -- Idempotente: usa IF NOT EXISTS / WHERE NOT EXISTS -- ============================================= -- ───────────────────────────────────────────── -- Tabla: diezmo_tipos_salida -- Catálogo de tipos de salida (Entrega al Pastor, Gastos, etc.) -- ───────────────────────────────────────────── CREATE TABLE IF NOT EXISTS public.diezmo_tipos_salida ( id bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY (INCREMENT 1 START 1 MINVALUE 1 CACHE 1), nombre varchar(100) NOT NULL, descripcion varchar(300), es_entrega_pastor boolean NOT NULL DEFAULT false, activo boolean NOT NULL DEFAULT true, eliminado boolean NOT NULL DEFAULT false, creado_en timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP, creado_por varchar(100), actualizado_en timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT diezmo_tipos_salida_pkey PRIMARY KEY (id) ); COMMENT ON TABLE public.diezmo_tipos_salida IS 'Catálogo de tipos de salida del módulo de diezmos'; INSERT INTO public.diezmo_tipos_salida (nombre, descripcion, es_entrega_pastor, activo) SELECT 'Entrega al Pastor', 'Entrega oficial de diezmos al pastor', true, true WHERE NOT EXISTS (SELECT 1 FROM public.diezmo_tipos_salida WHERE es_entrega_pastor = true); INSERT INTO public.diezmo_tipos_salida (nombre, descripcion, es_entrega_pastor, activo) SELECT 'Gastos Administrativos', 'Gastos operativos de la iglesia', false, true WHERE NOT EXISTS (SELECT 1 FROM public.diezmo_tipos_salida WHERE nombre = 'Gastos Administrativos'); -- ───────────────────────────────────────────── -- Tabla: diezmo_beneficiarios -- Personas o entidades que reciben salidas -- ───────────────────────────────────────────── CREATE TABLE IF NOT EXISTS public.diezmo_beneficiarios ( id bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY (INCREMENT 1 START 1 MINVALUE 1 CACHE 1), nombre varchar(150) NOT NULL, descripcion varchar(300), activo boolean NOT NULL DEFAULT true, eliminado boolean NOT NULL DEFAULT false, creado_en timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP, creado_por varchar(100), actualizado_en timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP, actualizado_por varchar(100), CONSTRAINT diezmo_beneficiarios_pkey PRIMARY KEY (id) ); COMMENT ON TABLE public.diezmo_beneficiarios IS 'Personas o entidades beneficiarias de salidas de diezmos'; -- ───────────────────────────────────────────── -- Tabla: diezmo_cierres -- Agregado raíz — un cierre por fecha (UNIQUE) -- ───────────────────────────────────────────── CREATE TABLE IF NOT EXISTS public.diezmo_cierres ( id bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY (INCREMENT 1 START 1 MINVALUE 1 CACHE 1), fecha date NOT NULL, cerrado boolean NOT NULL DEFAULT false, fecha_cierre timestamptz, cerrado_por varchar(100), observaciones varchar(500), total_recibido numeric(12,2) NOT NULL DEFAULT 0, total_cambio numeric(12,2) NOT NULL DEFAULT 0, total_neto numeric(12,2) NOT NULL DEFAULT 0, total_salidas numeric(12,2) NOT NULL DEFAULT 0, saldo_final numeric(12,2) NOT NULL DEFAULT 0, creado_en timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP, creado_por varchar(100), actualizado_en timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP, actualizado_por varchar(100), eliminado boolean NOT NULL DEFAULT false, CONSTRAINT diezmo_cierres_pkey PRIMARY KEY (id), CONSTRAINT diezmo_cierres_fecha_uq UNIQUE (fecha) ); COMMENT ON TABLE public.diezmo_cierres IS 'Cierres periódicos del módulo de diezmos (un registro por fecha)'; CREATE INDEX IF NOT EXISTS idx_diezmo_cierres_fecha ON public.diezmo_cierres (fecha); CREATE INDEX IF NOT EXISTS idx_diezmo_cierres_cerrado ON public.diezmo_cierres (cerrado); CREATE INDEX IF NOT EXISTS idx_diezmo_cierres_eliminado ON public.diezmo_cierres (eliminado); -- ───────────────────────────────────────────── -- Tabla: diezmo_detalles -- Diezmo individual por miembro dentro de un cierre -- ───────────────────────────────────────────── CREATE TABLE IF NOT EXISTS public.diezmo_detalles ( id bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY (INCREMENT 1 START 1 MINVALUE 1 CACHE 1), diezmo_cierre_id bigint NOT NULL, miembro_id bigint NOT NULL, monto_entregado numeric(12,2) NOT NULL CHECK (monto_entregado >= 0), cambio_entregado numeric(12,2) NOT NULL DEFAULT 0 CHECK (cambio_entregado >= 0), monto_neto numeric(12,2) NOT NULL DEFAULT 0, observaciones varchar(300), fecha timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP, creado_por varchar(100), creado_en timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP, actualizado_en timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP, actualizado_por varchar(100), eliminado boolean NOT NULL DEFAULT false, CONSTRAINT diezmo_detalles_pkey PRIMARY KEY (id), CONSTRAINT fk_diezmo_detalles_cierre FOREIGN KEY (diezmo_cierre_id) REFERENCES public.diezmo_cierres (id) ON UPDATE CASCADE ON DELETE CASCADE, CONSTRAINT fk_diezmo_detalles_miembro FOREIGN KEY (miembro_id) REFERENCES public.miembros (id) ON UPDATE CASCADE ON DELETE RESTRICT ); COMMENT ON TABLE public.diezmo_detalles IS 'Diezmos individuales aportados por miembro en cada cierre'; CREATE INDEX IF NOT EXISTS idx_diezmo_detalles_cierre_id ON public.diezmo_detalles (diezmo_cierre_id); CREATE INDEX IF NOT EXISTS idx_diezmo_detalles_miembro_id ON public.diezmo_detalles (miembro_id); CREATE INDEX IF NOT EXISTS idx_diezmo_detalles_eliminado ON public.diezmo_detalles (eliminado); -- ───────────────────────────────────────────── -- Tabla: diezmo_salidas -- Salida de fondos registrada contra un cierre -- ───────────────────────────────────────────── CREATE TABLE IF NOT EXISTS public.diezmo_salidas ( id bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY (INCREMENT 1 START 1 MINVALUE 1 CACHE 1), diezmo_cierre_id bigint NOT NULL, tipo_salida_id bigint NOT NULL, beneficiario_id bigint, monto numeric(12,2) NOT NULL CHECK (monto > 0), concepto varchar(300) NOT NULL, numero_recibo varchar(30), fecha timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP, creado_por varchar(100), creado_en timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP, actualizado_en timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP, eliminado boolean NOT NULL DEFAULT false, CONSTRAINT diezmo_salidas_pkey PRIMARY KEY (id), CONSTRAINT fk_diezmo_salidas_cierre FOREIGN KEY (diezmo_cierre_id) REFERENCES public.diezmo_cierres (id) ON UPDATE CASCADE ON DELETE CASCADE, CONSTRAINT fk_diezmo_salidas_tipo FOREIGN KEY (tipo_salida_id) REFERENCES public.diezmo_tipos_salida (id) ON UPDATE CASCADE ON DELETE RESTRICT, CONSTRAINT fk_diezmo_salidas_beneficiario FOREIGN KEY (beneficiario_id) REFERENCES public.diezmo_beneficiarios (id) ON UPDATE CASCADE ON DELETE RESTRICT ); COMMENT ON TABLE public.diezmo_salidas IS 'Salidas de fondos (entregas, gastos) registradas en un cierre de diezmos'; CREATE INDEX IF NOT EXISTS idx_diezmo_salidas_cierre_id ON public.diezmo_salidas (diezmo_cierre_id); CREATE INDEX IF NOT EXISTS idx_diezmo_salidas_eliminado ON public.diezmo_salidas (eliminado); -- ============================================= -- Bitácora de operaciones críticas del módulo -- ============================================= CREATE TABLE IF NOT EXISTS public.diezmo_bitacora ( id bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY (INCREMENT 1 START 1 MINVALUE 1 CACHE 1), diezmo_cierre_id bigint, accion varchar(50) NOT NULL, -- 'CIERRE', 'REAPERTURA', 'ELIMINAR_DETALLE', 'ELIMINAR_SALIDA' detalle varchar(500), realizado_por varchar(100) NOT NULL, realizado_en timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT diezmo_bitacora_pkey PRIMARY KEY (id) ); CREATE INDEX IF NOT EXISTS idx_diezmo_bitacora_cierre_id ON public.diezmo_bitacora (diezmo_cierre_id); -- ============================================= -- Permisos para el módulo -- ============================================= -- Crear módulo si no existe INSERT INTO public.modulos (nombre, descripcion, icono, orden, activo) SELECT 'Diezmos', 'Módulo de gestión de diezmos', 'bi bi-cash-coin', 50, true WHERE NOT EXISTS (SELECT 1 FROM public.modulos WHERE nombre = 'Diezmos'); -- Permiso: ver listado de cierres INSERT INTO public.permisos (codigo, nombre, descripcion, modulo_id, activo) SELECT 'Diezmo.Index', 'Ver Diezmos', 'Permite ver el listado de cierres de diezmos', (SELECT id FROM public.modulos WHERE nombre = 'Diezmos'), true WHERE NOT EXISTS (SELECT 1 FROM public.permisos WHERE codigo = 'Diezmo.Index'); -- Permiso: crear cierre INSERT INTO public.permisos (codigo, nombre, descripcion, modulo_id, activo) SELECT 'Diezmo.Create', 'Crear Cierre', 'Permite crear un nuevo cierre de diezmos', (SELECT id FROM public.modulos WHERE nombre = 'Diezmos'), true WHERE NOT EXISTS (SELECT 1 FROM public.permisos WHERE codigo = 'Diezmo.Create'); -- Permiso: registrar detalle (diezmo por miembro) INSERT INTO public.permisos (codigo, nombre, descripcion, modulo_id, activo) SELECT 'Diezmo.AddDetalle', 'Registrar Detalle', 'Permite agregar/eliminar diezmos de miembros en un cierre', (SELECT id FROM public.modulos WHERE nombre = 'Diezmos'), true WHERE NOT EXISTS (SELECT 1 FROM public.permisos WHERE codigo = 'Diezmo.AddDetalle'); -- Permiso: registrar salida INSERT INTO public.permisos (codigo, nombre, descripcion, modulo_id, activo) SELECT 'Diezmo.AddSalida', 'Registrar Salida', 'Permite registrar salidas/entregas en un cierre', (SELECT id FROM public.modulos WHERE nombre = 'Diezmos'), true WHERE NOT EXISTS (SELECT 1 FROM public.permisos WHERE codigo = 'Diezmo.AddSalida'); -- Permiso: cerrar cierre INSERT INTO public.permisos (codigo, nombre, descripcion, modulo_id, activo) SELECT 'Diezmo.Close', 'Cerrar Cierre', 'Permite cerrar un cierre de diezmos (bloquea edición)', (SELECT id FROM public.modulos WHERE nombre = 'Diezmos'), true WHERE NOT EXISTS (SELECT 1 FROM public.permisos WHERE codigo = 'Diezmo.Close'); -- Permiso: reabrir cierre (solo Administrador) INSERT INTO public.permisos (codigo, nombre, descripcion, modulo_id, activo) SELECT 'Diezmo.Reopen', 'Reabrir Cierre', 'Permite reabrir un cierre cerrado (solo Administrador)', (SELECT id FROM public.modulos WHERE nombre = 'Diezmos'), true WHERE NOT EXISTS (SELECT 1 FROM public.permisos WHERE codigo = 'Diezmo.Reopen'); -- Permiso: reportes y consultas INSERT INTO public.permisos (codigo, nombre, descripcion, modulo_id, activo) SELECT 'Diezmo.Reportes', 'Reportes Diezmos', 'Permite ver reportes y estado de cuenta del módulo de diezmos', (SELECT id FROM public.modulos WHERE nombre = 'Diezmos'), true WHERE NOT EXISTS (SELECT 1 FROM public.permisos WHERE codigo = 'Diezmo.Reportes');