948 lines
30 KiB
Markdown
948 lines
30 KiB
Markdown
# Sistema de Gestión de Documentos para Proyectos de Ingeniería - ARCH
|
|
|
|
## 1. Visión General del Proyecto
|
|
|
|
ARCH es un sistema de gestión documental diseñado específicamente para equipos de ingeniería, con el propósito de almacenar, organizar y versionar los archivos críticos de cada proyecto. La aplicación proporciona una estructura jerárquica para proyectos, control de versiones para documentos, y esquemas personalizables según el tipo de proyecto.
|
|
|
|
### Objetivos Principales
|
|
|
|
- Proporcionar un repositorio centralizado para documentación técnica de proyectos
|
|
- Mantener un historial completo de versiones de cada documento
|
|
- Establecer un sistema de permisos basado en niveles de usuario
|
|
- Facilitar la búsqueda y recuperación de información de proyectos
|
|
- Implementar una arquitectura simple y robusta basada en archivos para facilitar el mantenimiento y backups
|
|
|
|
### Principios de Diseño
|
|
|
|
- **Simplicidad**: Enfoque en funcionalidades esenciales con arquitectura sencilla
|
|
- **Robustez**: Control de versiones confiable y validación de datos
|
|
- **Seguridad**: Sistema de permisos granular y validación de archivos
|
|
- **Mantenibilidad**: Estructura basada en archivos JSON para fácil inspección y backup
|
|
- **Escalabilidad**: Diseño modular que permite agregar funcionalidades en el futuro
|
|
|
|
## 2. Arquitectura del Sistema
|
|
|
|
### 2.1 Enfoque Técnico
|
|
|
|
La aplicación sigue una arquitectura basada en archivos JSON y sistema de ficheros, eliminando la necesidad de una base de datos relacional. Esto proporciona:
|
|
|
|
- Facilidad de backup del sistema completo
|
|
- Inspección directa de datos mediante editores de texto
|
|
- Estructura de datos transparente
|
|
- Almacenamiento jerárquico que refleja la organización de proyectos
|
|
|
|
### 2.2 Componentes del Sistema
|
|
|
|
```
|
|
+-------------------+ +-------------------+ +-------------------+
|
|
| Interfaz Web | | Lógica de | | Sistema de |
|
|
| (Flask + Jinja) |----->| Negocio |----->| Archivos |
|
|
| | | (Servicios) | | (JSON) |
|
|
+-------------------+ +-------------------+ +-------------------+
|
|
^ ^ ^
|
|
| | |
|
|
v v v
|
|
+-------------------+ +-------------------+ +-------------------+
|
|
| Autenticación | | Validación | | Indexación |
|
|
| (Flask-Login) | | (WTForms) | | (Servicio) |
|
|
+-------------------+ +-------------------+ +-------------------+
|
|
```
|
|
|
|
### 2.3 Flujo de Datos
|
|
|
|
1. El usuario interactúa con la interfaz web
|
|
2. El sistema autentica y verifica permisos
|
|
3. Los controladores (rutas) procesan la solicitud
|
|
4. Los servicios implementan la lógica de negocio
|
|
5. Los datos se almacenan/recuperan del sistema de archivos
|
|
6. Se devuelve la respuesta formateada al usuario
|
|
|
|
## 3. Modelo de Datos
|
|
|
|
### 3.1 Usuarios
|
|
|
|
**Ubicación**: `/storage/users/users.json`
|
|
|
|
```json
|
|
{
|
|
"usuario1": {
|
|
"nombre": "Nombre Completo",
|
|
"username": "usuario1",
|
|
"email": "usuario1@ejemplo.com",
|
|
"password_hash": "hash_seguro_bcrypt",
|
|
"nivel": 5000,
|
|
"idioma": "es",
|
|
"fecha_caducidad": "2024-12-31",
|
|
"empresa": "Empresa A",
|
|
"estado": "activo",
|
|
"ultimo_acceso": "2023-06-15T14:30:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3.2 Tipos de Archivo
|
|
|
|
**Ubicación**: `/storage/filetypes/filetypes.json`
|
|
|
|
```json
|
|
{
|
|
"pdf": {
|
|
"extension": "pdf",
|
|
"descripcion": "Documento PDF",
|
|
"mime_type": "application/pdf",
|
|
"tamano_maximo": 20971520
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3.3 Esquemas
|
|
|
|
**Ubicación**: `/storage/schemas/schema.json`
|
|
|
|
```json
|
|
{
|
|
"ESQ001": {
|
|
"codigo": "ESQ001",
|
|
"descripcion": "Proyecto estándar",
|
|
"fecha_creacion": "2023-05-10T10:00:00Z",
|
|
"creado_por": "admin",
|
|
"documentos": [
|
|
{
|
|
"tipo": "pdf",
|
|
"nombre": "Manual de Usuario",
|
|
"nivel_ver": 0,
|
|
"nivel_editar": 5000
|
|
},
|
|
{
|
|
"tipo": "dwg",
|
|
"nombre": "Planos Técnicos",
|
|
"nivel_ver": 0,
|
|
"nivel_editar": 5000
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3.4 Proyectos
|
|
|
|
**Ubicación**: `/storage/projects/@id_num_@project_name_dir/project_meta.json`
|
|
|
|
```json
|
|
{
|
|
"codigo": "PROJ001",
|
|
"proyecto_padre": null,
|
|
"esquema": "ESQ001",
|
|
"descripcion": "Proyecto de ejemplo",
|
|
"cliente": "Cliente A",
|
|
"destinacion": "Planta Norte",
|
|
"ano_creacion": 2023,
|
|
"fecha_creacion": "2023-06-01T09:30:00Z",
|
|
"creado_por": "usuario1",
|
|
"estado": "activo",
|
|
"ultima_modificacion": "2023-06-15T14:30:00Z",
|
|
"modificado_por": "usuario2"
|
|
}
|
|
```
|
|
|
|
### 3.5 Documentos
|
|
|
|
**Ubicación**: `/storage/projects/@id_num_@project_name_dir/documents/@id_num_@doc_name/meta.json`
|
|
|
|
```json
|
|
{
|
|
"document_id": "001_manual_usuario",
|
|
"original_filename": "manual_v1.pdf",
|
|
"versions": [
|
|
{
|
|
"version": 1,
|
|
"filename": "v001_manual_usuario.pdf",
|
|
"created_at": "2023-06-10T11:30:00Z",
|
|
"created_by": "usuario1",
|
|
"description": "Versión inicial del manual",
|
|
"file_size": 1234567,
|
|
"mime_type": "application/pdf",
|
|
"checksum": "7b9fc3fc8438d11a52d8ec5e4d274c6dfa2520c5ac3afeb5d9a46d3b67c8bdc9",
|
|
"downloads": [
|
|
{
|
|
"user_id": "usuario2",
|
|
"downloaded_at": "2023-06-11T15:45:00Z"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## 4. Estructura de Archivos y Directorios
|
|
|
|
```
|
|
document_manager/
|
|
│
|
|
├── app.py # Punto de entrada de la aplicación
|
|
├── config.py # Configuración global (entornos, rutas, etc.)
|
|
├── requirements.txt # Dependencias del proyecto
|
|
├── README.md # Documentación básica
|
|
│
|
|
├── services/ # Lógica de negocio
|
|
│ ├── __init__.py
|
|
│ ├── auth_service.py # Servicio de autenticación
|
|
│ ├── user_service.py # Gestión de usuarios
|
|
│ ├── project_service.py # Gestión de proyectos
|
|
│ ├── document_service.py # Gestión de documentos
|
|
│ ├── schema_service.py # Gestión de esquemas
|
|
│ ├── export_service.py # Exportación de proyectos
|
|
│ └── index_service.py # Servicio de indexación
|
|
│
|
|
├── utils/ # Utilidades generales
|
|
│ ├── __init__.py
|
|
│ ├── file_utils.py # Utilidades para manejo de archivos
|
|
│ ├── security.py # Funciones de seguridad (hash, validación)
|
|
│ ├── validators.py # Validadores de datos
|
|
│ └── logger.py # Configuración de logs
|
|
│
|
|
├── middleware/ # Middleware para Flask
|
|
│ ├── __init__.py
|
|
│ ├── auth_middleware.py # Verificación de autenticación
|
|
│ └── permission_check.py # Verificación de permisos
|
|
│
|
|
├── routes/ # Endpoints de la API
|
|
│ ├── __init__.py
|
|
│ ├── auth_routes.py # Rutas de autenticación (login/logout)
|
|
│ ├── user_routes.py # Rutas de gestión de usuarios
|
|
│ ├── project_routes.py # Rutas de gestión de proyectos
|
|
│ ├── document_routes.py # Rutas de gestión de documentos
|
|
│ ├── schema_routes.py # Rutas de gestión de esquemas
|
|
│ └── admin_routes.py # Rutas administrativas
|
|
│
|
|
├── static/ # Archivos estáticos
|
|
│ ├── css/
|
|
│ │ ├── bootstrap.min.css # Framework CSS
|
|
│ │ ├── main.css # Estilos generales
|
|
│ │ ├── login.css # Estilos de login
|
|
│ │ ├── projects.css # Estilos para proyectos
|
|
│ │ └── documents.css # Estilos para documentos
|
|
│ │
|
|
│ ├── js/
|
|
│ │ ├── lib/ # Librerías JavaScript externas
|
|
│ │ │ ├── bootstrap.bundle.min.js
|
|
│ │ │ └── jquery.min.js
|
|
│ │ │
|
|
│ │ ├── auth.js # Funciones de autenticación
|
|
│ │ ├── projects.js # Funciones para proyectos
|
|
│ │ ├── documents.js # Funciones para documentos
|
|
│ │ ├── schemas.js # Funciones para esquemas
|
|
│ │ ├── users.js # Funciones para gestión de usuarios
|
|
│ │ └── admin.js # Funciones administrativas
|
|
│ │
|
|
│ └── img/
|
|
│ ├── logo.png # Logo del sistema
|
|
│ ├── icons/ # Iconos de la interfaz
|
|
│ └── file-types/ # Iconos para tipos de archivo
|
|
│
|
|
├── templates/ # Plantillas HTML
|
|
│ ├── base.html # Plantilla base
|
|
│ ├── error.html # Páginas de error
|
|
│ │
|
|
│ ├── auth/ # Plantillas de autenticación
|
|
│ │ ├── login.html
|
|
│ │ └── reset_password.html
|
|
│ │
|
|
│ ├── projects/ # Plantillas de proyectos
|
|
│ │ ├── list.html # Lista de proyectos
|
|
│ │ ├── create.html # Crear proyecto
|
|
│ │ ├── edit.html # Editar proyecto
|
|
│ │ └── view.html # Ver proyecto
|
|
│ │
|
|
│ ├── documents/ # Plantillas de documentos
|
|
│ │ ├── list.html # Lista de documentos
|
|
│ │ ├── upload.html # Subir documento
|
|
│ │ ├── versions.html # Ver versiones
|
|
│ │ └── download.html # Descargar documento
|
|
│ │
|
|
│ ├── schemas/ # Plantillas de esquemas
|
|
│ │ ├── list.html # Lista de esquemas
|
|
│ │ ├── create.html # Crear esquema
|
|
│ │ └── edit.html # Editar esquema
|
|
│ │
|
|
│ ├── users/ # Plantillas de usuarios
|
|
│ │ ├── list.html # Lista de usuarios
|
|
│ │ ├── create.html # Crear usuario
|
|
│ │ └── edit.html # Editar usuario
|
|
│ │
|
|
│ └── admin/ # Plantillas administrativas
|
|
│ ├── dashboard.html # Panel de administración
|
|
│ ├── filetypes.html # Gestión de tipos de archivo
|
|
│ └── system.html # Diagnóstico del sistema
|
|
│
|
|
├── tests/ # Pruebas unitarias y de integración
|
|
│ ├── __init__.py
|
|
│ ├── conftest.py # Configuración y fixtures para pytest
|
|
│ ├── test_auth.py # Pruebas de autenticación
|
|
│ ├── test_projects.py # Pruebas de proyectos
|
|
│ ├── test_documents.py # Pruebas de documentos
|
|
│ ├── test_schemas.py # Pruebas de esquemas
|
|
│ └── json_reporter.py # Reportero personalizado para JSON
|
|
│
|
|
└── storage/ # Almacenamiento de datos
|
|
├── indices.json # Índices centralizados
|
|
├── logs/ # Directorio para logs
|
|
│ ├── access.log # Registro de accesos
|
|
│ ├── error.log # Registro de errores
|
|
│ └── system.log # Registro del sistema
|
|
│
|
|
├── schemas/
|
|
│ ├── schema.json # Lista de Esquemas
|
|
│
|
|
├── users/
|
|
│ ├── users.json # Usuarios del sistema
|
|
│
|
|
├── filetypes/
|
|
│ ├── filetypes.json # Tipos de archivo permitidos
|
|
│
|
|
└── projects/
|
|
├── @id_num_@project_name_dir/
|
|
│ ├── project_meta.json # Metadatos del proyecto
|
|
│ ├── schema.json # Esquema usado en particular
|
|
│ ├── permissions.json # Permisos de acceso
|
|
│ └── documents/ # Documentos del proyecto
|
|
│ ├── @id_num_@doc_name/
|
|
│ │ ├── v001_doc_name # Archivo versión 1
|
|
│ │ ├── v002_doc_name # Archivo versión 2
|
|
│ │ ├── meta.json # Metadatos y versiones
|
|
│ └── ...
|
|
└── ...
|
|
```
|
|
|
|
## 5. Librerías y Dependencias
|
|
|
|
### 5.1 Lista de Dependencias
|
|
|
|
```
|
|
# Componentes principales
|
|
Flask==2.3.3
|
|
Werkzeug==2.3.7
|
|
Jinja2==3.1.2
|
|
itsdangerous==2.1.2
|
|
click==8.1.3
|
|
|
|
# Gestión de formularios y validación
|
|
Flask-WTF==1.2.1
|
|
WTForms==3.0.1
|
|
|
|
# Autenticación y seguridad
|
|
Flask-Login==0.6.2
|
|
Flask-Bcrypt==1.0.1
|
|
|
|
# Manejo de fechas y zonas horarias
|
|
python-dateutil==2.8.2
|
|
pytz==2023.3
|
|
|
|
# Configuración y entorno
|
|
python-dotenv==1.0.0
|
|
|
|
# Gestión de sesiones
|
|
Flask-Session==0.5.0
|
|
|
|
# HTTP y comunicaciones
|
|
requests==2.31.0
|
|
|
|
# Validación de archivos
|
|
python-magic==0.4.27
|
|
|
|
# Mejoras de desarrollo y mantenimiento
|
|
loguru==0.7.0
|
|
pytest==7.4.0
|
|
pytest-cov==4.1.0
|
|
pytest-html==3.2.0
|
|
|
|
# Servidor de producción
|
|
gunicorn==21.2.0
|
|
|
|
# Programación de tareas
|
|
APScheduler==3.10.1
|
|
|
|
# Caché
|
|
Flask-Caching==2.0.2
|
|
```
|
|
|
|
### 5.2 Propósito de Cada Librería
|
|
|
|
#### Componentes Esenciales
|
|
- **Flask**: Framework web principal para toda la aplicación
|
|
- **Werkzeug, Jinja2, itsdangerous, click**: Dependencias de Flask
|
|
|
|
#### Formularios y Validación
|
|
- **Flask-WTF, WTForms**: Manejo de formularios con validación (creación/edición de proyectos, documentos)
|
|
|
|
#### Autenticación y Seguridad
|
|
- **Flask-Login**: Gestión de autenticación de usuarios
|
|
- **Flask-Bcrypt**: Hash seguro de contraseñas
|
|
|
|
#### Fechas y Zonas Horarias
|
|
- **python-dateutil, pytz**: Manipulación avanzada de fechas en metadatos
|
|
|
|
#### Configuración
|
|
- **python-dotenv**: Manejo de variables de entorno para diferentes ambientes
|
|
|
|
#### Sesiones
|
|
- **Flask-Session**: Gestión avanzada de sesiones (timeout, backend personalizable)
|
|
|
|
#### Comunicaciones
|
|
- **requests**: Para comunicaciones HTTP (si se requieren integraciones futuras)
|
|
|
|
#### Validación de Archivos
|
|
- **python-magic**: Detección del tipo real de archivos (seguridad)
|
|
|
|
#### Desarrollo y Mantenimiento
|
|
- **loguru**: Sistema de logging mejorado
|
|
- **pytest, pytest-cov, pytest-html**: Framework de pruebas con generación de reportes
|
|
- **gunicorn**: Servidor WSGI para producción
|
|
- **APScheduler**: Tareas programadas (mantenimiento, backups)
|
|
- **Flask-Caching**: Sistema de caché para optimizar rendimiento
|
|
|
|
## 6. Funcionalidades del Sistema
|
|
|
|
### 6.1 Gestión de Usuarios
|
|
- Registro de nuevos usuarios (solo por administradores)
|
|
- Autenticación mediante usuario y contraseña
|
|
- Gestión de niveles de acceso
|
|
- Perfiles de usuario
|
|
- Reseteo de contraseñas
|
|
- Tiempo de expiración de sesión (timeout)
|
|
|
|
### 6.2 Gestión de Proyectos
|
|
- Creación y configuración de proyectos
|
|
- Estructura jerárquica (proyectos padre/hijo)
|
|
- Asignación de esquemas
|
|
- Búsqueda avanzada de proyectos
|
|
- Filtrado por múltiples criterios
|
|
|
|
### 6.3 Gestión de Documentos
|
|
- Carga y descarga de documentos
|
|
- Versionado completo con historial
|
|
- Validación de tipos de archivo
|
|
- Registro de descargas para auditoría
|
|
- Metadatos y descripciones por versión
|
|
- Exportación de proyectos con la última versión de documentos
|
|
|
|
### 6.4 Gestión de Esquemas
|
|
- Definición de esquemas de proyecto
|
|
- Asignación de tipos de documentos
|
|
- Configuración de permisos por tipo de documento
|
|
- Personalización de esquemas para proyectos individuales
|
|
|
|
### 6.5 Administración del Sistema
|
|
- Configuración de tipos de archivo permitidos
|
|
- Diagnóstico del estado del sistema
|
|
- Logs de actividad para auditoría
|
|
- Gestión de usuarios y permisos
|
|
|
|
## 7. Flujos de Trabajo Principales
|
|
|
|
### 7.1 Autenticación de Usuario
|
|
```
|
|
+-------------+ +-------------+ +--------------+ +----------------+
|
|
| Acceso a | | Formulario | | Verificación | | Redirección a |
|
|
| sistema |---->| de login |---->| credenciales |---->| panel principal|
|
|
+-------------+ +-------------+ +--------------+ +----------------+
|
|
|
|
|
| [Error]
|
|
v
|
|
+-------------+
|
|
| Mensaje de |
|
|
| error |
|
|
+-------------+
|
|
```
|
|
|
|
### 7.2 Creación de Proyecto
|
|
```
|
|
+----------------+ +---------------+ +---------------+ +----------------+
|
|
| Usuario accede | | Formulario de | | Validación de | | Asignación de |
|
|
| a "Crear |---->| nuevo proyecto|---->| datos |---->| ID y creación |
|
|
| Proyecto" | | | | | | de estructura |
|
|
+----------------+ +---------------+ +---------------+ +----------------+
|
|
|
|
|
v
|
|
+----------------+
|
|
| Redirección a |
|
|
| vista de |
|
|
| proyecto |
|
|
+----------------+
|
|
```
|
|
|
|
### 7.3 Gestión de Documentos
|
|
```
|
|
+----------------+ +----------------+ +----------------+ +----------------+
|
|
| Usuario accede | | Visualización | | Carga de | | Creación de |
|
|
| a proyecto |---->| de documentos |---->| documento o |---->| nueva versión |
|
|
| | | del proyecto | | nueva versión | | con metadatos |
|
|
+----------------+ +----------------+ +----------------+ +----------------+
|
|
|
|
|
| [Ver historial]
|
|
v
|
|
+----------------+ +----------------+
|
|
| Visualización | | Opción de |
|
|
| de versiones |---->| descarga de |
|
|
| del documento | | versión |
|
|
+----------------+ +----------------+
|
|
```
|
|
|
|
### 7.4 Exportación de Proyecto
|
|
```
|
|
+----------------+ +----------------+ +----------------+ +----------------+
|
|
| Usuario | | Selección de | | Sistema | | Descarga del |
|
|
| selecciona |---->| documentos a |---->| empaqueta |---->| archivo ZIP |
|
|
| "Exportar" | | exportar | | documentos | | con documentos |
|
|
+----------------+ +----------------+ +----------------+ +----------------+
|
|
```
|
|
|
|
## 8. Seguridad del Sistema
|
|
|
|
### 8.1 Autenticación
|
|
- Contraseñas almacenadas con hash seguro (bcrypt)
|
|
- Timeout de sesión por inactividad
|
|
- Protección contra fuerza bruta (límite de intentos)
|
|
|
|
### 8.2 Autorización
|
|
- Sistema de niveles de acceso granular
|
|
- Verificación de permisos en cada operación
|
|
- Separación de responsabilidades por nivel
|
|
|
|
### 8.3 Seguridad de Archivos
|
|
- Validación de tipos de archivo mediante contenido (python-magic)
|
|
- Almacenamiento de checksums para verificar integridad
|
|
- Limitación de tamaño por tipo de archivo
|
|
|
|
### 8.4 Logging y Auditoría
|
|
- Registro de todas las acciones importantes
|
|
- Log de accesos para auditoría
|
|
- Tracking de descargas de documentos
|
|
|
|
## 9. Estrategia de Pruebas
|
|
|
|
### 9.1 Framework de Pruebas
|
|
- Uso de pytest como framework principal
|
|
- Cobertura de código con pytest-cov
|
|
- Generación de reportes en JSON para análisis
|
|
|
|
### 9.2 Estructura de Pruebas
|
|
```
|
|
tests/
|
|
├── conftest.py # Configuración y fixtures compartidos
|
|
├── test_auth.py # Pruebas de autenticación
|
|
├── test_projects.py # Pruebas de gestión de proyectos
|
|
├── test_documents.py # Pruebas de gestión de documentos
|
|
├── test_schemas.py # Pruebas de esquemas
|
|
└── json_reporter.py # Plugin para generar reportes JSON
|
|
```
|
|
|
|
### 9.3 Casos de Prueba Principales
|
|
- Autenticación de usuarios
|
|
- Creación y gestión de proyectos
|
|
- Carga, versión y descarga de documentos
|
|
- Validación de esquemas
|
|
- Verificación de permisos
|
|
- Exportación de proyectos
|
|
|
|
### 9.4 Generación de Reportes
|
|
Se implementará un plugin personalizado para pytest que generará reportes en formato JSON, incluyendo:
|
|
- Cantidad de pruebas ejecutadas
|
|
- Resultados (éxito/fallo)
|
|
- Duración de cada prueba
|
|
- Cobertura de código
|
|
- Detalles de errores encontrados
|
|
|
|
### 9.5 Ejemplo de Configuración de Pytest
|
|
|
|
```python
|
|
# conftest.py
|
|
|
|
import pytest
|
|
import os
|
|
import json
|
|
import shutil
|
|
from app import create_app
|
|
|
|
@pytest.fixture
|
|
def app():
|
|
"""Crear una instancia de la aplicación para pruebas."""
|
|
# Configuración de prueba
|
|
test_config = {
|
|
'TESTING': True,
|
|
'STORAGE_PATH': 'test_storage',
|
|
'SECRET_KEY': 'test_key'
|
|
}
|
|
|
|
# Crear directorio de almacenamiento para pruebas
|
|
if not os.path.exists('test_storage'):
|
|
os.makedirs('test_storage')
|
|
|
|
# Crear estructura básica
|
|
for dir in ['users', 'schemas', 'filetypes', 'projects', 'logs']:
|
|
if not os.path.exists(f'test_storage/{dir}'):
|
|
os.makedirs(f'test_storage/{dir}')
|
|
|
|
# Crear app con configuración de prueba
|
|
app = create_app(test_config)
|
|
|
|
yield app
|
|
|
|
# Limpiar después de las pruebas
|
|
shutil.rmtree('test_storage')
|
|
|
|
@pytest.fixture
|
|
def client(app):
|
|
"""Cliente de prueba para la aplicación."""
|
|
return app.test_client()
|
|
|
|
@pytest.fixture
|
|
def auth(client):
|
|
"""Helper para pruebas de autenticación."""
|
|
class AuthActions:
|
|
def login(self, username='admin', password='password'):
|
|
return client.post('/login', data={
|
|
'username': username,
|
|
'password': password
|
|
}, follow_redirects=True)
|
|
|
|
def logout(self):
|
|
return client.get('/logout', follow_redirects=True)
|
|
|
|
return AuthActions()
|
|
```
|
|
|
|
```python
|
|
# json_reporter.py
|
|
|
|
import json
|
|
import pytest
|
|
import datetime
|
|
import os
|
|
|
|
class JSONReporter:
|
|
def __init__(self, config):
|
|
self.config = config
|
|
self.results = {
|
|
'summary': {
|
|
'total': 0,
|
|
'passed': 0,
|
|
'failed': 0,
|
|
'skipped': 0,
|
|
'duration': 0,
|
|
'timestamp': datetime.datetime.now().isoformat()
|
|
},
|
|
'tests': []
|
|
}
|
|
|
|
def pytest_runtest_logreport(self, report):
|
|
if report.when == 'call' or (report.when == 'setup' and report.skipped):
|
|
self.results['summary']['total'] += 1
|
|
|
|
if report.passed:
|
|
result = 'passed'
|
|
self.results['summary']['passed'] += 1
|
|
elif report.failed:
|
|
result = 'failed'
|
|
self.results['summary']['failed'] += 1
|
|
else:
|
|
result = 'skipped'
|
|
self.results['summary']['skipped'] += 1
|
|
|
|
self.results['tests'].append({
|
|
'name': report.nodeid,
|
|
'result': result,
|
|
'duration': report.duration,
|
|
'error': str(report.longrepr) if hasattr(report, 'longrepr') and report.longrepr else None
|
|
})
|
|
|
|
def pytest_sessionfinish(self, session):
|
|
self.results['summary']['duration'] = session.config.hook.pytest_report_teststatus.get_duration()
|
|
|
|
with open('test_results.json', 'w') as f:
|
|
json.dump(self.results, f, indent=2)
|
|
|
|
@pytest.hookimpl(trylast=True)
|
|
def pytest_configure(config):
|
|
config.pluginmanager.register(JSONReporter(config), 'json_reporter')
|
|
```
|
|
|
|
## 10. Guía de Implementación
|
|
|
|
### 10.1 Configuración del Entorno
|
|
|
|
1. Crear entorno virtual:
|
|
```bash
|
|
python -m venv venv
|
|
source venv/bin/activate # Linux/Mac
|
|
venv\Scripts\activate # Windows
|
|
```
|
|
|
|
2. Instalar dependencias:
|
|
```bash
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
3. Configurar variables de entorno (crear archivo `.env`):
|
|
```
|
|
FLASK_APP=app.py
|
|
FLASK_ENV=development
|
|
SECRET_KEY=clave_secreta_generada
|
|
STORAGE_PATH=storage
|
|
```
|
|
|
|
### 10.2 Inicialización del Sistema
|
|
|
|
1. Crear estructura de directorios:
|
|
```bash
|
|
mkdir -p storage/{logs,schemas,users,filetypes,projects}
|
|
```
|
|
|
|
2. Inicializar archivos base:
|
|
```python
|
|
# Script para inicializar archivos base
|
|
import json
|
|
import os
|
|
import bcrypt
|
|
|
|
# Crear usuarios iniciales
|
|
admin_password = bcrypt.hashpw("admin123".encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
|
|
users = {
|
|
"admin": {
|
|
"nombre": "Administrador",
|
|
"username": "admin",
|
|
"email": "admin@ejemplo.com",
|
|
"password_hash": admin_password,
|
|
"nivel": 9999,
|
|
"idioma": "es",
|
|
"fecha_caducidad": None,
|
|
"empresa": "ARCH",
|
|
"estado": "activo"
|
|
}
|
|
}
|
|
|
|
# Crear tipos de archivo iniciales
|
|
filetypes = {
|
|
"pdf": {
|
|
"extension": "pdf",
|
|
"descripcion": "Documento PDF",
|
|
"mime_type": "application/pdf",
|
|
"tamano_maximo": 20971520 # 20MB
|
|
},
|
|
"txt": {
|
|
"extension": "txt",
|
|
"descripcion": "Documento de texto",
|
|
"mime_type": "text/plain",
|
|
"tamano_maximo": 5242880 # 5MB
|
|
},
|
|
"zip": {
|
|
"extension": "zip",
|
|
"descripcion": "Archivo comprimido",
|
|
"mime_type": "application/zip",
|
|
"tamano_maximo": 104857600 # 100MB
|
|
}
|
|
}
|
|
|
|
# Crear esquema inicial
|
|
schemas = {
|
|
"ESQ001": {
|
|
"codigo": "ESQ001",
|
|
"descripcion": "Proyecto estándar",
|
|
"fecha_creacion": "2023-05-10T10:00:00Z",
|
|
"creado_por": "admin",
|
|
"documentos": [
|
|
{
|
|
"tipo": "pdf",
|
|
"nombre": "Manual de Usuario",
|
|
"nivel_ver": 0,
|
|
"nivel_editar": 5000
|
|
},
|
|
{
|
|
"tipo": "zip",
|
|
"nombre": "Archivos Fuente",
|
|
"nivel_ver": 5000,
|
|
"nivel_editar": 5000
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
# Guardar archivos
|
|
with open('storage/users/users.json', 'w') as f:
|
|
json.dump(users, f, indent=2)
|
|
|
|
with open('storage/filetypes/filetypes.json', 'w') as f:
|
|
json.dump(filetypes, f, indent=2)
|
|
|
|
with open('storage/schemas/schema.json', 'w') as f:
|
|
json.dump(schemas, f, indent=2)
|
|
|
|
with open('storage/indices.json', 'w') as f:
|
|
json.dump({"max_project_id": 0, "max_document_id": 0}, f, indent=2)
|
|
|
|
print("Sistema inicializado correctamente.")
|
|
```
|
|
|
|
### 10.3 Orden de Implementación
|
|
|
|
1. **Fase 1: Estructura básica y autenticación**
|
|
- Configuración del proyecto
|
|
- Sistema de autenticación
|
|
- Plantillas base
|
|
- Gestión de usuarios
|
|
|
|
2. **Fase 2: Gestión de proyectos**
|
|
- Creación y edición de proyectos
|
|
- Búsqueda y filtrado
|
|
- Estructura jerárquica
|
|
|
|
3. **Fase 3: Gestión de documentos**
|
|
- Carga y descarga de documentos
|
|
- Sistema de versionado
|
|
- Visualización de historiales
|
|
|
|
4. **Fase 4: Esquemas y personalización**
|
|
- Gestión de esquemas
|
|
- Asignación a proyectos
|
|
- Configuración de tipos de documentos
|
|
|
|
5. **Fase 5: Funciones avanzadas**
|
|
- Exportación de proyectos
|
|
- Sistema de logs
|
|
- Diagnóstico del sistema
|
|
|
|
### 10.4 Ejecución de Pruebas
|
|
|
|
Durante el desarrollo, ejecutar pruebas regularmente:
|
|
|
|
```bash
|
|
pytest -v --cov=app tests/
|
|
```
|
|
|
|
Para generar el reporte JSON:
|
|
|
|
```bash
|
|
pytest -v --cov=app tests/ --json-report
|
|
```
|
|
|
|
## 11. Operación y Mantenimiento
|
|
|
|
### 11.1 Backups
|
|
|
|
Se recomienda realizar backups regulares del directorio `storage/` completo:
|
|
|
|
```bash
|
|
# Script simple de backup
|
|
tar -czf backup-$(date +%Y%m%d).tar.gz storage/
|
|
```
|
|
|
|
Para automatización, se puede configurar APScheduler:
|
|
|
|
```python
|
|
from apscheduler.schedulers.background import BackgroundScheduler
|
|
from apscheduler.triggers.cron import CronTrigger
|
|
import subprocess
|
|
import os
|
|
from datetime import datetime
|
|
|
|
def backup_storage():
|
|
"""Realizar backup del directorio storage."""
|
|
backup_dir = "backups"
|
|
if not os.path.exists(backup_dir):
|
|
os.makedirs(backup_dir)
|
|
|
|
backup_file = f"{backup_dir}/backup-{datetime.now().strftime('%Y%m%d-%H%M%S')}.tar.gz"
|
|
subprocess.run(["tar", "-czf", backup_file, "storage/"])
|
|
|
|
# Eliminar backups antiguos (mantener solo los últimos 5)
|
|
backups = sorted([f for f in os.listdir(backup_dir) if f.startswith("backup-")])
|
|
if len(backups) > 5:
|
|
for old_backup in backups[:-5]:
|
|
os.remove(os.path.join(backup_dir, old_backup))
|
|
|
|
# Configurar scheduler
|
|
scheduler = BackgroundScheduler()
|
|
scheduler.add_job(
|
|
backup_storage,
|
|
CronTrigger(hour=2, minute=0), # Ejecutar a las 2:00 AM
|
|
id='backup_job',
|
|
replace_existing=True
|
|
)
|
|
scheduler.start()
|
|
```
|
|
|
|
### 11.2 Monitoreo del Sistema
|
|
|
|
Implementar endpoints para monitoreo:
|
|
|
|
```python
|
|
@admin_routes.route('/system/status')
|
|
@login_required
|
|
@permission_required(9999)
|
|
def system_status():
|
|
"""Mostrar estado del sistema."""
|
|
storage_info = {
|
|
'projects': len(os.listdir('storage/projects')),
|
|
'users': len(json.load(open('storage/users/users.json', 'r'))),
|
|
'schemas': len(json.load(open('storage/schemas/schema.json', 'r'))),
|
|
'disk_usage': get_directory_size('storage') // (1024 * 1024) # MB
|
|
}
|
|
|
|
return render_template('admin/system.html', storage_info=storage_info)
|
|
```
|
|
|
|
### 11.3 Rotación de Logs
|
|
|
|
```python
|
|
import logging
|
|
from logging.handlers import RotatingFileHandler
|
|
|
|
# Configurar logger para accesos
|
|
access_logger = logging.getLogger('access')
|
|
access_handler = RotatingFileHandler(
|
|
'storage/logs/access.log',
|
|
maxBytes=10485760, # 10MB
|
|
backupCount=5
|
|
)
|
|
access_logger.addHandler(access_handler)
|
|
|
|
# Configurar logger para errores
|
|
error_logger = logging.getLogger('error')
|
|
error_handler = RotatingFileHandler(
|
|
'storage/logs/error.log',
|
|
maxBytes=10485760, # 10MB
|
|
backupCount=5
|
|
)
|
|
error_logger.addHandler(error_handler)
|
|
```
|
|
|
|
## 12. Consideraciones Adicionales
|
|
|
|
### 12.1 Rendimiento
|
|
|
|
- Para proyectos con muchos documentos, implementar paginación
|
|
- Utilizar Flask-Caching para mejorar tiempos de respuesta
|
|
- Considerar indexación avanzada para búsquedas en proyectos grandes
|
|
|
|
### 12.2 Escalabilidad
|
|
|
|
- La arquitectura basada en archivos es adecuada para equipos pequeños/medianos
|
|
- Para volúmenes muy grandes, considerar migración a base de datos
|
|
- Separar almacenamiento de documentos en un sistema dedicado si crecen significativamente
|
|
|
|
### 12.3 Interfaz de Usuario
|
|
|
|
- Diseño responsive para acceso desde diferentes dispositivos
|
|
- Interacciones AJAX para operaciones frecuentes sin recargar la página
|
|
- Feedback visual claro durante operaciones de carga/descarga
|
|
|
|
### 12.4 Futuras Extensiones
|
|
|
|
- Integración con servicios de almacenamiento en la nube
|
|
- Sistema de notificaciones para cambios en documentos
|
|
- Vista previa de documentos en el navegador
|
|
- Anotaciones y comentarios en documentos
|
|
|
|
---
|
|
|
|
Este documento proporciona una guía completa para la implementación del Sistema de Gestión de Documentos ARCH. Siguiendo esta estructura y consideraciones, se puede desarrollar un sistema robusto y funcional que cumpla con los requisitos establecidos, manteniendo la simplicidad y eficiencia como prioridad. |