[MAE-016] feat: Add documents schema DDL with 11 tables and 8 ENUMs
- document_categories: Categorias jerarquicas - documents: Registro principal - document_versions: Control de versiones - document_permissions: Permisos granulares - approval_workflows: Definicion de flujos - approval_instances: Instancias de aprobacion - approval_steps: Pasos de aprobacion - approval_actions: Acciones de aprobacion - annotations: Anotaciones sobre documentos - access_logs: Historial de acceso - document_shares: Compartidos externos Includes: RLS, indices, triggers, fulltext search Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
e927cafc90
commit
80dd204db2
832
schemas/10-documents-schema-ddl.sql
Normal file
832
schemas/10-documents-schema-ddl.sql
Normal file
@ -0,0 +1,832 @@
|
||||
-- ============================================================================
|
||||
-- 10-documents-schema-ddl.sql
|
||||
-- Schema: documents
|
||||
-- ERP Construccion - Modulo Gestion Documental (MAE-016)
|
||||
-- ============================================================================
|
||||
-- Descripcion: Sistema de gestion documental incluyendo:
|
||||
-- - Repositorio de documentos estructurado
|
||||
-- - Control de versiones
|
||||
-- - Flujos de aprobacion
|
||||
-- - Permisos granulares
|
||||
-- - Anotaciones sobre planos
|
||||
-- - Integracion con almacenamiento externo (S3)
|
||||
-- ============================================================================
|
||||
-- Autor: Claude-Arquitecto-Orquestador
|
||||
-- Fecha: 2026-01-25
|
||||
-- Version: 1.0.0
|
||||
-- ============================================================================
|
||||
|
||||
-- Crear schema si no existe
|
||||
CREATE SCHEMA IF NOT EXISTS documents;
|
||||
|
||||
-- ============================================================================
|
||||
-- ENUMS
|
||||
-- ============================================================================
|
||||
|
||||
-- Tipo de documento
|
||||
CREATE TYPE documents.document_type AS ENUM (
|
||||
'plan', -- Planos arquitectonicos/estructurales
|
||||
'specification', -- Especificaciones tecnicas
|
||||
'contract', -- Contratos
|
||||
'permit', -- Permisos y licencias
|
||||
'report', -- Reportes
|
||||
'photograph', -- Fotografias
|
||||
'drawing', -- Dibujos y croquis
|
||||
'manual', -- Manuales
|
||||
'procedure', -- Procedimientos
|
||||
'form', -- Formatos
|
||||
'correspondence', -- Correspondencia
|
||||
'invoice', -- Facturas
|
||||
'estimate', -- Estimaciones/Presupuestos
|
||||
'other' -- Otro
|
||||
);
|
||||
|
||||
-- Estado del documento
|
||||
CREATE TYPE documents.document_status AS ENUM (
|
||||
'draft', -- Borrador
|
||||
'pending_review', -- Pendiente de revision
|
||||
'in_review', -- En revision
|
||||
'approved', -- Aprobado
|
||||
'rejected', -- Rechazado
|
||||
'obsolete', -- Obsoleto
|
||||
'archived' -- Archivado
|
||||
);
|
||||
|
||||
-- Nivel de acceso
|
||||
CREATE TYPE documents.access_level AS ENUM (
|
||||
'public', -- Publico (todos en el tenant)
|
||||
'internal', -- Interno (empleados)
|
||||
'confidential', -- Confidencial
|
||||
'restricted' -- Restringido (solo autorizados)
|
||||
);
|
||||
|
||||
-- Estado de version
|
||||
CREATE TYPE documents.version_status AS ENUM (
|
||||
'current', -- Version actual
|
||||
'superseded', -- Reemplazada
|
||||
'archived' -- Archivada
|
||||
);
|
||||
|
||||
-- Estado de flujo de aprobacion
|
||||
CREATE TYPE documents.workflow_status AS ENUM (
|
||||
'draft', -- Borrador
|
||||
'pending', -- Pendiente
|
||||
'in_progress', -- En progreso
|
||||
'approved', -- Aprobado
|
||||
'rejected', -- Rechazado
|
||||
'cancelled' -- Cancelado
|
||||
);
|
||||
|
||||
-- Tipo de paso de aprobacion
|
||||
CREATE TYPE documents.approval_step_type AS ENUM (
|
||||
'review', -- Revision
|
||||
'approval', -- Aprobacion
|
||||
'signature', -- Firma
|
||||
'comment' -- Solo comentario
|
||||
);
|
||||
|
||||
-- Accion de aprobacion
|
||||
CREATE TYPE documents.approval_action AS ENUM (
|
||||
'approve', -- Aprobar
|
||||
'reject', -- Rechazar
|
||||
'request_changes' -- Solicitar cambios
|
||||
);
|
||||
|
||||
-- Tipo de anotacion
|
||||
CREATE TYPE documents.annotation_type AS ENUM (
|
||||
'comment', -- Comentario
|
||||
'markup', -- Marcado
|
||||
'highlight', -- Resaltado
|
||||
'arrow', -- Flecha
|
||||
'dimension', -- Dimension
|
||||
'stamp', -- Sello
|
||||
'signature' -- Firma
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- TABLAS
|
||||
-- ============================================================================
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 1. Categorias de Documentos
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE documents.document_categories (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Informacion basica
|
||||
code VARCHAR(50) NOT NULL,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
description TEXT,
|
||||
|
||||
-- Jerarquia
|
||||
parent_id UUID REFERENCES documents.document_categories(id),
|
||||
level INTEGER NOT NULL DEFAULT 1,
|
||||
path VARCHAR(500), -- Path completo separado por /
|
||||
|
||||
-- Configuracion
|
||||
default_access_level documents.access_level DEFAULT 'internal',
|
||||
requires_approval BOOLEAN DEFAULT FALSE,
|
||||
retention_days INTEGER, -- Tiempo de retencion en dias
|
||||
allowed_extensions VARCHAR(255)[], -- Extensiones permitidas
|
||||
|
||||
-- Icono y color
|
||||
icon VARCHAR(50),
|
||||
color VARCHAR(20),
|
||||
|
||||
-- Estado
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
sort_order INTEGER DEFAULT 0,
|
||||
|
||||
-- Metadatos
|
||||
metadata JSONB,
|
||||
|
||||
-- Auditoria
|
||||
created_by UUID,
|
||||
updated_by UUID,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ,
|
||||
|
||||
CONSTRAINT uq_document_categories_tenant_code UNIQUE (tenant_id, code)
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 2. Documentos (Registro Principal)
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE documents.documents (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Identificacion
|
||||
document_code VARCHAR(100) NOT NULL,
|
||||
title VARCHAR(500) NOT NULL,
|
||||
description TEXT,
|
||||
|
||||
-- Clasificacion
|
||||
category_id UUID REFERENCES documents.document_categories(id),
|
||||
document_type documents.document_type NOT NULL,
|
||||
status documents.document_status NOT NULL DEFAULT 'draft',
|
||||
access_level documents.access_level NOT NULL DEFAULT 'internal',
|
||||
|
||||
-- Version actual
|
||||
current_version_id UUID, -- Se actualiza con trigger
|
||||
current_version_number VARCHAR(20) DEFAULT '1.0',
|
||||
|
||||
-- Proyecto/Contexto
|
||||
project_id UUID,
|
||||
project_code VARCHAR(50),
|
||||
project_name VARCHAR(255),
|
||||
|
||||
-- Metadatos del documento
|
||||
author VARCHAR(255),
|
||||
keywords VARCHAR(255)[],
|
||||
tags VARCHAR(100)[],
|
||||
|
||||
-- Fechas importantes
|
||||
document_date DATE,
|
||||
effective_date DATE,
|
||||
expiry_date DATE,
|
||||
review_date DATE,
|
||||
|
||||
-- Origen
|
||||
source VARCHAR(100), -- internal, external, contractor
|
||||
external_reference VARCHAR(255), -- Referencia externa si aplica
|
||||
original_filename VARCHAR(500),
|
||||
|
||||
-- Relaciones
|
||||
parent_document_id UUID REFERENCES documents.documents(id), -- Documento padre
|
||||
related_documents UUID[], -- Array de IDs relacionados
|
||||
|
||||
-- Flujo de aprobacion
|
||||
requires_approval BOOLEAN DEFAULT FALSE,
|
||||
current_workflow_id UUID,
|
||||
approved_by_id UUID,
|
||||
approved_at TIMESTAMPTZ,
|
||||
|
||||
-- Estadisticas
|
||||
view_count INTEGER DEFAULT 0,
|
||||
download_count INTEGER DEFAULT 0,
|
||||
last_accessed_at TIMESTAMPTZ,
|
||||
|
||||
-- Flags
|
||||
is_template BOOLEAN DEFAULT FALSE,
|
||||
is_locked BOOLEAN DEFAULT FALSE,
|
||||
locked_by_id UUID,
|
||||
locked_at TIMESTAMPTZ,
|
||||
|
||||
-- Notas y metadatos
|
||||
notes TEXT,
|
||||
custom_fields JSONB,
|
||||
metadata JSONB,
|
||||
|
||||
-- Auditoria
|
||||
created_by UUID,
|
||||
updated_by UUID,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ,
|
||||
|
||||
CONSTRAINT uq_documents_tenant_code UNIQUE (tenant_id, document_code)
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 3. Versiones de Documentos
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE documents.document_versions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Documento padre
|
||||
document_id UUID NOT NULL REFERENCES documents.documents(id) ON DELETE CASCADE,
|
||||
|
||||
-- Version
|
||||
version_number VARCHAR(20) NOT NULL,
|
||||
version_label VARCHAR(100), -- Etiqueta opcional (ej: "Final", "Para construccion")
|
||||
status documents.version_status NOT NULL DEFAULT 'current',
|
||||
|
||||
-- Archivo
|
||||
file_name VARCHAR(500) NOT NULL,
|
||||
file_extension VARCHAR(20) NOT NULL,
|
||||
file_size_bytes BIGINT NOT NULL,
|
||||
mime_type VARCHAR(100),
|
||||
checksum_md5 VARCHAR(32),
|
||||
checksum_sha256 VARCHAR(64),
|
||||
|
||||
-- Almacenamiento
|
||||
storage_provider VARCHAR(50) NOT NULL DEFAULT 's3', -- s3, azure, local
|
||||
storage_bucket VARCHAR(255),
|
||||
storage_key VARCHAR(1000) NOT NULL, -- Path en el storage
|
||||
storage_url VARCHAR(2000), -- URL de acceso
|
||||
thumbnail_url VARCHAR(2000),
|
||||
preview_url VARCHAR(2000),
|
||||
|
||||
-- Procesamiento
|
||||
is_processed BOOLEAN DEFAULT FALSE,
|
||||
ocr_text TEXT, -- Texto extraido por OCR
|
||||
extracted_metadata JSONB,
|
||||
|
||||
-- Paginas (para PDFs/planos)
|
||||
page_count INTEGER,
|
||||
page_dimensions JSONB, -- Dimensiones por pagina
|
||||
|
||||
-- Cambios
|
||||
change_summary TEXT,
|
||||
change_type VARCHAR(50), -- major, minor, patch
|
||||
|
||||
-- Subido por
|
||||
uploaded_by_id UUID,
|
||||
uploaded_by_name VARCHAR(255),
|
||||
upload_source VARCHAR(50), -- web, mobile, api, email
|
||||
|
||||
-- Auditoria
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
superseded_at TIMESTAMPTZ,
|
||||
superseded_by_version_id UUID
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 4. Permisos de Documentos
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE documents.document_permissions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Objeto
|
||||
document_id UUID REFERENCES documents.documents(id) ON DELETE CASCADE,
|
||||
category_id UUID REFERENCES documents.document_categories(id) ON DELETE CASCADE,
|
||||
|
||||
-- Sujeto (quien tiene el permiso)
|
||||
user_id UUID,
|
||||
role_id UUID,
|
||||
team_id UUID,
|
||||
|
||||
-- Permisos
|
||||
can_view BOOLEAN DEFAULT FALSE,
|
||||
can_download BOOLEAN DEFAULT FALSE,
|
||||
can_edit BOOLEAN DEFAULT FALSE,
|
||||
can_delete BOOLEAN DEFAULT FALSE,
|
||||
can_share BOOLEAN DEFAULT FALSE,
|
||||
can_approve BOOLEAN DEFAULT FALSE,
|
||||
can_annotate BOOLEAN DEFAULT FALSE,
|
||||
|
||||
-- Vigencia
|
||||
valid_from TIMESTAMPTZ,
|
||||
valid_until TIMESTAMPTZ,
|
||||
|
||||
-- Otorgado por
|
||||
granted_by_id UUID,
|
||||
granted_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
|
||||
-- Auditoria
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
|
||||
CONSTRAINT chk_permission_target CHECK (
|
||||
(document_id IS NOT NULL AND category_id IS NULL) OR
|
||||
(document_id IS NULL AND category_id IS NOT NULL)
|
||||
),
|
||||
CONSTRAINT chk_permission_subject CHECK (
|
||||
(user_id IS NOT NULL AND role_id IS NULL AND team_id IS NULL) OR
|
||||
(user_id IS NULL AND role_id IS NOT NULL AND team_id IS NULL) OR
|
||||
(user_id IS NULL AND role_id IS NULL AND team_id IS NOT NULL)
|
||||
)
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 5. Flujos de Aprobacion (Definicion)
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE documents.approval_workflows (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Identificacion
|
||||
workflow_code VARCHAR(50) NOT NULL,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
|
||||
-- Aplica a
|
||||
category_id UUID REFERENCES documents.document_categories(id),
|
||||
document_type documents.document_type,
|
||||
|
||||
-- Pasos (JSON array con la definicion)
|
||||
steps JSONB NOT NULL, -- [{step_number, name, type, approvers[], required_count}]
|
||||
|
||||
-- Configuracion
|
||||
allow_parallel BOOLEAN DEFAULT FALSE, -- Pasos pueden ser paralelos
|
||||
allow_skip BOOLEAN DEFAULT FALSE, -- Permitir saltar pasos
|
||||
auto_archive_on_approval BOOLEAN DEFAULT FALSE,
|
||||
|
||||
-- Estado
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
|
||||
-- Metadatos
|
||||
metadata JSONB,
|
||||
|
||||
-- Auditoria
|
||||
created_by UUID,
|
||||
updated_by UUID,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ,
|
||||
|
||||
CONSTRAINT uq_approval_workflows_tenant_code UNIQUE (tenant_id, workflow_code)
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 6. Instancias de Flujo de Aprobacion
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE documents.approval_instances (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Flujo y documento
|
||||
workflow_id UUID NOT NULL REFERENCES documents.approval_workflows(id),
|
||||
document_id UUID NOT NULL REFERENCES documents.documents(id),
|
||||
version_id UUID REFERENCES documents.document_versions(id),
|
||||
|
||||
-- Estado
|
||||
status documents.workflow_status NOT NULL DEFAULT 'draft',
|
||||
current_step INTEGER DEFAULT 1,
|
||||
total_steps INTEGER NOT NULL,
|
||||
|
||||
-- Fechas
|
||||
started_at TIMESTAMPTZ,
|
||||
completed_at TIMESTAMPTZ,
|
||||
due_date TIMESTAMPTZ,
|
||||
|
||||
-- Iniciador
|
||||
initiated_by_id UUID,
|
||||
initiated_by_name VARCHAR(255),
|
||||
|
||||
-- Resultado final
|
||||
final_action documents.approval_action,
|
||||
final_comments TEXT,
|
||||
final_approver_id UUID,
|
||||
|
||||
-- Notas
|
||||
notes TEXT,
|
||||
metadata JSONB,
|
||||
|
||||
-- Auditoria
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 7. Pasos de Aprobacion (Instancias)
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE documents.approval_steps (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Instancia
|
||||
instance_id UUID NOT NULL REFERENCES documents.approval_instances(id) ON DELETE CASCADE,
|
||||
|
||||
-- Paso
|
||||
step_number INTEGER NOT NULL,
|
||||
step_name VARCHAR(255) NOT NULL,
|
||||
step_type documents.approval_step_type NOT NULL,
|
||||
|
||||
-- Aprobadores requeridos
|
||||
required_approvers UUID[], -- IDs de usuarios requeridos
|
||||
required_count INTEGER DEFAULT 1, -- Cuantas aprobaciones se necesitan
|
||||
|
||||
-- Estado
|
||||
status documents.workflow_status NOT NULL DEFAULT 'pending',
|
||||
|
||||
-- Fechas
|
||||
started_at TIMESTAMPTZ,
|
||||
completed_at TIMESTAMPTZ,
|
||||
due_date TIMESTAMPTZ,
|
||||
|
||||
-- Resultado
|
||||
action_taken documents.approval_action,
|
||||
approved_by UUID[],
|
||||
rejected_by UUID[],
|
||||
|
||||
-- Notas
|
||||
notes TEXT,
|
||||
|
||||
-- Auditoria
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 8. Acciones de Aprobacion
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE documents.approval_actions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Paso
|
||||
step_id UUID NOT NULL REFERENCES documents.approval_steps(id) ON DELETE CASCADE,
|
||||
instance_id UUID NOT NULL REFERENCES documents.approval_instances(id),
|
||||
|
||||
-- Accion
|
||||
action documents.approval_action NOT NULL,
|
||||
comments TEXT,
|
||||
|
||||
-- Usuario que toma la accion
|
||||
user_id UUID NOT NULL,
|
||||
user_name VARCHAR(255),
|
||||
|
||||
-- Firma digital (si aplica)
|
||||
signature_data TEXT,
|
||||
signature_timestamp TIMESTAMPTZ,
|
||||
signature_ip VARCHAR(45),
|
||||
|
||||
-- Auditoria
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 9. Anotaciones sobre Documentos
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE documents.annotations (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Documento y version
|
||||
document_id UUID NOT NULL REFERENCES documents.documents(id) ON DELETE CASCADE,
|
||||
version_id UUID REFERENCES documents.document_versions(id),
|
||||
|
||||
-- Tipo
|
||||
annotation_type documents.annotation_type NOT NULL,
|
||||
|
||||
-- Ubicacion en el documento
|
||||
page_number INTEGER,
|
||||
x_position DECIMAL(10,4),
|
||||
y_position DECIMAL(10,4),
|
||||
width DECIMAL(10,4),
|
||||
height DECIMAL(10,4),
|
||||
rotation DECIMAL(5,2),
|
||||
|
||||
-- Contenido
|
||||
content TEXT, -- Texto del comentario o SVG del dibujo
|
||||
style JSONB, -- Estilos (color, grosor, fuente, etc.)
|
||||
|
||||
-- Respuesta a otra anotacion
|
||||
parent_annotation_id UUID REFERENCES documents.annotations(id),
|
||||
|
||||
-- Estado
|
||||
is_resolved BOOLEAN DEFAULT FALSE,
|
||||
resolved_by_id UUID,
|
||||
resolved_at TIMESTAMPTZ,
|
||||
|
||||
-- Visibilidad
|
||||
is_private BOOLEAN DEFAULT FALSE,
|
||||
visible_to UUID[], -- Array de user_ids si es privado
|
||||
|
||||
-- Autor
|
||||
author_id UUID NOT NULL,
|
||||
author_name VARCHAR(255),
|
||||
|
||||
-- Auditoria
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 10. Historial de Acceso a Documentos
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE documents.access_logs (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Documento
|
||||
document_id UUID NOT NULL REFERENCES documents.documents(id),
|
||||
version_id UUID REFERENCES documents.document_versions(id),
|
||||
|
||||
-- Accion
|
||||
action VARCHAR(50) NOT NULL, -- view, download, print, share, edit
|
||||
action_details JSONB,
|
||||
|
||||
-- Usuario
|
||||
user_id UUID NOT NULL,
|
||||
user_name VARCHAR(255),
|
||||
user_ip VARCHAR(45),
|
||||
user_agent TEXT,
|
||||
|
||||
-- Contexto
|
||||
session_id VARCHAR(100),
|
||||
request_source VARCHAR(50), -- web, mobile, api
|
||||
|
||||
-- Timestamp
|
||||
accessed_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 11. Compartidos Externos
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE documents.document_shares (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Documento
|
||||
document_id UUID NOT NULL REFERENCES documents.documents(id) ON DELETE CASCADE,
|
||||
version_id UUID REFERENCES documents.document_versions(id),
|
||||
|
||||
-- Link compartido
|
||||
share_token VARCHAR(100) NOT NULL UNIQUE,
|
||||
share_url VARCHAR(2000),
|
||||
|
||||
-- Destinatario
|
||||
shared_with_email VARCHAR(255),
|
||||
shared_with_name VARCHAR(255),
|
||||
|
||||
-- Permisos
|
||||
can_download BOOLEAN DEFAULT FALSE,
|
||||
can_comment BOOLEAN DEFAULT FALSE,
|
||||
|
||||
-- Seguridad
|
||||
password_hash VARCHAR(255), -- Si requiere password
|
||||
max_downloads INTEGER,
|
||||
download_count INTEGER DEFAULT 0,
|
||||
|
||||
-- Vigencia
|
||||
expires_at TIMESTAMPTZ,
|
||||
is_revoked BOOLEAN DEFAULT FALSE,
|
||||
revoked_at TIMESTAMPTZ,
|
||||
revoked_by_id UUID,
|
||||
|
||||
-- Compartido por
|
||||
shared_by_id UUID NOT NULL,
|
||||
shared_by_name VARCHAR(255),
|
||||
|
||||
-- Notificacion
|
||||
notification_sent BOOLEAN DEFAULT FALSE,
|
||||
notification_sent_at TIMESTAMPTZ,
|
||||
|
||||
-- Auditoria
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
last_accessed_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- INDICES
|
||||
-- ============================================================================
|
||||
|
||||
-- Document Categories
|
||||
CREATE INDEX idx_document_categories_tenant ON documents.document_categories(tenant_id);
|
||||
CREATE INDEX idx_document_categories_parent ON documents.document_categories(parent_id);
|
||||
|
||||
-- Documents
|
||||
CREATE INDEX idx_documents_tenant ON documents.documents(tenant_id);
|
||||
CREATE INDEX idx_documents_tenant_category ON documents.documents(tenant_id, category_id);
|
||||
CREATE INDEX idx_documents_tenant_type ON documents.documents(tenant_id, document_type);
|
||||
CREATE INDEX idx_documents_tenant_status ON documents.documents(tenant_id, status);
|
||||
CREATE INDEX idx_documents_tenant_project ON documents.documents(tenant_id, project_id);
|
||||
CREATE INDEX idx_documents_keywords ON documents.documents USING gin(keywords);
|
||||
CREATE INDEX idx_documents_tags ON documents.documents USING gin(tags);
|
||||
CREATE INDEX idx_documents_fulltext ON documents.documents USING gin(
|
||||
to_tsvector('spanish', coalesce(title, '') || ' ' || coalesce(description, ''))
|
||||
);
|
||||
|
||||
-- Document Versions
|
||||
CREATE INDEX idx_document_versions_tenant ON documents.document_versions(tenant_id);
|
||||
CREATE INDEX idx_document_versions_document ON documents.document_versions(document_id);
|
||||
CREATE INDEX idx_document_versions_status ON documents.document_versions(status);
|
||||
|
||||
-- Document Permissions
|
||||
CREATE INDEX idx_document_permissions_document ON documents.document_permissions(document_id);
|
||||
CREATE INDEX idx_document_permissions_category ON documents.document_permissions(category_id);
|
||||
CREATE INDEX idx_document_permissions_user ON documents.document_permissions(user_id);
|
||||
CREATE INDEX idx_document_permissions_role ON documents.document_permissions(role_id);
|
||||
|
||||
-- Approval Workflows
|
||||
CREATE INDEX idx_approval_workflows_tenant ON documents.approval_workflows(tenant_id);
|
||||
CREATE INDEX idx_approval_workflows_category ON documents.approval_workflows(category_id);
|
||||
|
||||
-- Approval Instances
|
||||
CREATE INDEX idx_approval_instances_tenant ON documents.approval_instances(tenant_id);
|
||||
CREATE INDEX idx_approval_instances_document ON documents.approval_instances(document_id);
|
||||
CREATE INDEX idx_approval_instances_status ON documents.approval_instances(status);
|
||||
|
||||
-- Approval Steps
|
||||
CREATE INDEX idx_approval_steps_instance ON documents.approval_steps(instance_id);
|
||||
CREATE INDEX idx_approval_steps_status ON documents.approval_steps(status);
|
||||
|
||||
-- Approval Actions
|
||||
CREATE INDEX idx_approval_actions_step ON documents.approval_actions(step_id);
|
||||
CREATE INDEX idx_approval_actions_user ON documents.approval_actions(user_id);
|
||||
|
||||
-- Annotations
|
||||
CREATE INDEX idx_annotations_tenant ON documents.annotations(tenant_id);
|
||||
CREATE INDEX idx_annotations_document ON documents.annotations(document_id);
|
||||
CREATE INDEX idx_annotations_version ON documents.annotations(version_id);
|
||||
CREATE INDEX idx_annotations_author ON documents.annotations(author_id);
|
||||
|
||||
-- Access Logs
|
||||
CREATE INDEX idx_access_logs_tenant ON documents.access_logs(tenant_id);
|
||||
CREATE INDEX idx_access_logs_document ON documents.access_logs(document_id);
|
||||
CREATE INDEX idx_access_logs_user ON documents.access_logs(user_id);
|
||||
CREATE INDEX idx_access_logs_accessed ON documents.access_logs(accessed_at);
|
||||
|
||||
-- Document Shares
|
||||
CREATE INDEX idx_document_shares_tenant ON documents.document_shares(tenant_id);
|
||||
CREATE INDEX idx_document_shares_document ON documents.document_shares(document_id);
|
||||
CREATE INDEX idx_document_shares_token ON documents.document_shares(share_token);
|
||||
|
||||
-- ============================================================================
|
||||
-- ROW LEVEL SECURITY (RLS)
|
||||
-- ============================================================================
|
||||
|
||||
ALTER TABLE documents.document_categories ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE documents.documents ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE documents.document_versions ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE documents.document_permissions ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE documents.approval_workflows ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE documents.approval_instances ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE documents.approval_steps ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE documents.approval_actions ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE documents.annotations ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE documents.access_logs ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE documents.document_shares ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- ============================================================================
|
||||
-- TRIGGERS DE AUDITORIA
|
||||
-- ============================================================================
|
||||
|
||||
CREATE OR REPLACE FUNCTION documents.set_updated_at()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_document_categories_updated_at
|
||||
BEFORE UPDATE ON documents.document_categories
|
||||
FOR EACH ROW EXECUTE FUNCTION documents.set_updated_at();
|
||||
|
||||
CREATE TRIGGER trg_documents_updated_at
|
||||
BEFORE UPDATE ON documents.documents
|
||||
FOR EACH ROW EXECUTE FUNCTION documents.set_updated_at();
|
||||
|
||||
CREATE TRIGGER trg_document_permissions_updated_at
|
||||
BEFORE UPDATE ON documents.document_permissions
|
||||
FOR EACH ROW EXECUTE FUNCTION documents.set_updated_at();
|
||||
|
||||
CREATE TRIGGER trg_approval_workflows_updated_at
|
||||
BEFORE UPDATE ON documents.approval_workflows
|
||||
FOR EACH ROW EXECUTE FUNCTION documents.set_updated_at();
|
||||
|
||||
CREATE TRIGGER trg_approval_instances_updated_at
|
||||
BEFORE UPDATE ON documents.approval_instances
|
||||
FOR EACH ROW EXECUTE FUNCTION documents.set_updated_at();
|
||||
|
||||
CREATE TRIGGER trg_approval_steps_updated_at
|
||||
BEFORE UPDATE ON documents.approval_steps
|
||||
FOR EACH ROW EXECUTE FUNCTION documents.set_updated_at();
|
||||
|
||||
CREATE TRIGGER trg_annotations_updated_at
|
||||
BEFORE UPDATE ON documents.annotations
|
||||
FOR EACH ROW EXECUTE FUNCTION documents.set_updated_at();
|
||||
|
||||
-- ============================================================================
|
||||
-- FUNCIONES AUXILIARES
|
||||
-- ============================================================================
|
||||
|
||||
-- Actualizar version actual del documento
|
||||
CREATE OR REPLACE FUNCTION documents.update_current_version()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
IF NEW.status = 'current' THEN
|
||||
-- Marcar versiones anteriores como superseded
|
||||
UPDATE documents.document_versions
|
||||
SET status = 'superseded',
|
||||
superseded_at = NOW(),
|
||||
superseded_by_version_id = NEW.id
|
||||
WHERE document_id = NEW.document_id
|
||||
AND id != NEW.id
|
||||
AND status = 'current';
|
||||
|
||||
-- Actualizar documento con version actual
|
||||
UPDATE documents.documents
|
||||
SET current_version_id = NEW.id,
|
||||
current_version_number = NEW.version_number,
|
||||
updated_at = NOW()
|
||||
WHERE id = NEW.document_id;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_update_current_version
|
||||
AFTER INSERT OR UPDATE ON documents.document_versions
|
||||
FOR EACH ROW EXECUTE FUNCTION documents.update_current_version();
|
||||
|
||||
-- Incrementar contador de vistas
|
||||
CREATE OR REPLACE FUNCTION documents.increment_view_count()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
IF NEW.action = 'view' THEN
|
||||
UPDATE documents.documents
|
||||
SET view_count = view_count + 1,
|
||||
last_accessed_at = NOW()
|
||||
WHERE id = NEW.document_id;
|
||||
ELSIF NEW.action = 'download' THEN
|
||||
UPDATE documents.documents
|
||||
SET download_count = download_count + 1,
|
||||
last_accessed_at = NOW()
|
||||
WHERE id = NEW.document_id;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_increment_view_count
|
||||
AFTER INSERT ON documents.access_logs
|
||||
FOR EACH ROW EXECUTE FUNCTION documents.increment_view_count();
|
||||
|
||||
-- Actualizar path de categoria
|
||||
CREATE OR REPLACE FUNCTION documents.update_category_path()
|
||||
RETURNS TRIGGER AS $$
|
||||
DECLARE
|
||||
v_parent_path VARCHAR(500);
|
||||
BEGIN
|
||||
IF NEW.parent_id IS NULL THEN
|
||||
NEW.path := '/' || NEW.code;
|
||||
NEW.level := 1;
|
||||
ELSE
|
||||
SELECT path, level + 1 INTO v_parent_path, NEW.level
|
||||
FROM documents.document_categories
|
||||
WHERE id = NEW.parent_id;
|
||||
|
||||
NEW.path := v_parent_path || '/' || NEW.code;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_update_category_path
|
||||
BEFORE INSERT OR UPDATE ON documents.document_categories
|
||||
FOR EACH ROW EXECUTE FUNCTION documents.update_category_path();
|
||||
|
||||
-- ============================================================================
|
||||
-- COMENTARIOS DE DOCUMENTACION
|
||||
-- ============================================================================
|
||||
|
||||
COMMENT ON SCHEMA documents IS 'Modulo de Gestion Documental (MAE-016) - ERP Construccion';
|
||||
|
||||
COMMENT ON TABLE documents.document_categories IS 'Categorias jerarquicas para clasificar documentos';
|
||||
COMMENT ON TABLE documents.documents IS 'Registro principal de documentos';
|
||||
COMMENT ON TABLE documents.document_versions IS 'Versiones de documentos con archivos';
|
||||
COMMENT ON TABLE documents.document_permissions IS 'Permisos granulares por documento o categoria';
|
||||
COMMENT ON TABLE documents.approval_workflows IS 'Definicion de flujos de aprobacion';
|
||||
COMMENT ON TABLE documents.approval_instances IS 'Instancias de flujos de aprobacion activos';
|
||||
COMMENT ON TABLE documents.approval_steps IS 'Pasos de aprobacion por instancia';
|
||||
COMMENT ON TABLE documents.approval_actions IS 'Acciones tomadas en pasos de aprobacion';
|
||||
COMMENT ON TABLE documents.annotations IS 'Anotaciones y comentarios sobre documentos';
|
||||
COMMENT ON TABLE documents.access_logs IS 'Historial de acceso a documentos';
|
||||
COMMENT ON TABLE documents.document_shares IS 'Links de compartido externo';
|
||||
|
||||
-- ============================================================================
|
||||
-- FIN DEL SCRIPT
|
||||
-- ============================================================================
|
||||
Loading…
Reference in New Issue
Block a user