- Auth: Login/Register con creacion de clinica - Dashboard: KPIs reales, graficas recharts - Pacientes: CRUD completo con busqueda - Agenda: FullCalendar, drag-and-drop, vista recepcion - Expediente: Notas SOAP, signos vitales, CIE-10 - Facturacion: Facturas con IVA, campos CFDI SAT - Inventario: Productos, stock, movimientos, alertas - Configuracion: Clinica, equipo, catalogo servicios - Supabase self-hosted: 18 tablas con RLS multi-tenant - Docker + Nginx para produccion Co-Authored-By: claude-flow <ruv@ruv.net>
42 lines
2.0 KiB
PL/PgSQL
42 lines
2.0 KiB
PL/PgSQL
CREATE TABLE audit_log (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
clinic_id UUID REFERENCES clinics(id),
|
|
user_id UUID,
|
|
table_name TEXT NOT NULL,
|
|
record_id UUID,
|
|
action TEXT NOT NULL CHECK (action IN ('INSERT','UPDATE','DELETE')),
|
|
old_data JSONB,
|
|
new_data JSONB,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX idx_audit_clinic ON audit_log(clinic_id, created_at DESC);
|
|
|
|
CREATE OR REPLACE FUNCTION audit_trigger_func()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
IF TG_OP = 'INSERT' THEN
|
|
INSERT INTO audit_log (clinic_id, user_id, table_name, record_id, action, new_data)
|
|
VALUES (NEW.clinic_id, auth.uid(), TG_TABLE_NAME, NEW.id, 'INSERT', to_jsonb(NEW));
|
|
RETURN NEW;
|
|
ELSIF TG_OP = 'UPDATE' THEN
|
|
INSERT INTO audit_log (clinic_id, user_id, table_name, record_id, action, old_data, new_data)
|
|
VALUES (NEW.clinic_id, auth.uid(), TG_TABLE_NAME, NEW.id, 'UPDATE', to_jsonb(OLD), to_jsonb(NEW));
|
|
RETURN NEW;
|
|
ELSIF TG_OP = 'DELETE' THEN
|
|
INSERT INTO audit_log (clinic_id, user_id, table_name, record_id, action, old_data)
|
|
VALUES (OLD.clinic_id, auth.uid(), TG_TABLE_NAME, OLD.id, 'DELETE', to_jsonb(OLD));
|
|
RETURN OLD;
|
|
END IF;
|
|
END;
|
|
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
|
|
|
CREATE TRIGGER audit_patients AFTER INSERT OR UPDATE OR DELETE ON patients FOR EACH ROW EXECUTE FUNCTION audit_trigger_func();
|
|
CREATE TRIGGER audit_appointments AFTER INSERT OR UPDATE OR DELETE ON appointments FOR EACH ROW EXECUTE FUNCTION audit_trigger_func();
|
|
CREATE TRIGGER audit_consultation_notes AFTER INSERT OR UPDATE OR DELETE ON consultation_notes FOR EACH ROW EXECUTE FUNCTION audit_trigger_func();
|
|
CREATE TRIGGER audit_invoices AFTER INSERT OR UPDATE OR DELETE ON invoices FOR EACH ROW EXECUTE FUNCTION audit_trigger_func();
|
|
CREATE TRIGGER audit_inventory_movements AFTER INSERT ON inventory_movements FOR EACH ROW EXECUTE FUNCTION audit_trigger_func();
|
|
|
|
ALTER TABLE audit_log ENABLE ROW LEVEL SECURITY;
|
|
CREATE POLICY "Admins view audit" ON audit_log FOR SELECT USING (clinic_id = auth.clinic_id());
|