feat: Initial commit - clinica-dental

ERP especializado para clínicas dentales.

Estructura inicial:
- database/ (PostgreSQL DDL)
- docs/ (Documentación)
- orchestration/ (Sistema NEXUS)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
rckrdmrd 2026-01-07 04:41:50 -06:00
commit 7ffcdf597c
12 changed files with 2321 additions and 0 deletions

307
.env.example Normal file
View File

@ -0,0 +1,307 @@
# =============================================================================
# .env.example - CLINICA DENTAL
# =============================================================================
# Copia este archivo a .env y configura los valores
# Generado por: @PERFIL_DEVENV
# Referencia: orchestration/environment/ENVIRONMENT-INVENTORY.yml
# =============================================================================
# =============================================================================
# APLICACION
# =============================================================================
NODE_ENV=development
APP_NAME=clinica-dental
APP_VERSION=1.0.0
# =============================================================================
# PUERTOS - Asignados por DEVENV-PORTS-INVENTORY.yml
# =============================================================================
FRONTEND_PORT=3130
BACKEND_PORT=3131
# Alias para compatibilidad
PORT=3131
# =============================================================================
# BASE DE DATOS - PostgreSQL
# =============================================================================
# Desarrollo: Puerto 5441 (asignado en DEVENV-PORTS-INVENTORY.yml)
# Produccion: Puerto 5432 (estandar)
# =============================================================================
DB_HOST=localhost
DB_PORT=5441
DB_NAME=clinica_dental_dev
DB_USER=dental_dev
# IMPORTANTE: Generar password seguro con: openssl rand -base64 32
DB_PASSWORD=CAMBIAR_POR_PASSWORD_SEGURO
# Connection string completo (calculado de las variables anteriores)
DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}
# Pool de conexiones
DB_POOL_SIZE=10
DB_CONNECTION_TIMEOUT=5000
# SSL (false para desarrollo, true para produccion)
DB_SSL=false
# =============================================================================
# BASE DE DATOS - Ambientes adicionales
# =============================================================================
# Test (mismo servidor, diferente BD)
# DB_NAME_TEST=clinica_dental_test
# Staging (servidor externo)
# DB_HOST_STAGING=staging-db.example.com
# DB_NAME_STAGING=clinica_dental_staging
# DB_USER_STAGING=dental_staging
# Produccion (servidor externo)
# DB_HOST_PROD=prod-db.example.com
# DB_NAME_PROD=clinica_dental_prod
# DB_USER_PROD=dental_prod
# =============================================================================
# REDIS - Cache y Sesiones
# =============================================================================
# Desarrollo: Puerto 6388 (asignado en DEVENV-PORTS-INVENTORY.yml)
# Produccion: Puerto 6379 (estandar)
# =============================================================================
REDIS_HOST=localhost
REDIS_PORT=6388
REDIS_DB=0
# Password (vacio para desarrollo, requerido en produccion)
REDIS_PASSWORD=
# Connection string
REDIS_URL=redis://${REDIS_HOST}:${REDIS_PORT}/${REDIS_DB}
# Configuracion de cache
REDIS_CACHE_TTL=3600
REDIS_MAX_MEMORY=256mb
# =============================================================================
# AUTENTICACION - JWT
# =============================================================================
# IMPORTANTE: Generar secreto seguro con: openssl rand -base64 64
# Minimo 32 caracteres requeridos
# =============================================================================
JWT_SECRET=CAMBIAR_POR_SECRETO_SEGURO_DE_AL_MENOS_32_CARACTERES
# Tiempos de expiracion
JWT_EXPIRES_IN=24h
JWT_REFRESH_EXPIRES_IN=7d
# Algoritmo (default: HS256)
JWT_ALGORITHM=HS256
# =============================================================================
# CORS - Cross-Origin Resource Sharing
# =============================================================================
FRONTEND_URL=http://localhost:3130
# Multiples origenes separados por coma
ALLOWED_ORIGINS=http://localhost:3130,http://localhost:3131
# Metodos permitidos
CORS_METHODS=GET,POST,PUT,PATCH,DELETE,OPTIONS
# Headers permitidos
CORS_HEADERS=Content-Type,Authorization,X-Requested-With
# =============================================================================
# LOGGING
# =============================================================================
# Niveles: debug, info, warn, error
LOG_LEVEL=debug
# Formatos: pretty (desarrollo), json (produccion)
LOG_FORMAT=pretty
# Archivo de logs (opcional)
# LOG_FILE=./logs/app.log
# Rotacion de logs
# LOG_MAX_SIZE=10m
# LOG_MAX_FILES=5
# =============================================================================
# ALMACENAMIENTO DE ARCHIVOS (Radiografias y documentos)
# =============================================================================
# Tipo: local, s3, minio
STORAGE_TYPE=local
# Path local (para desarrollo)
STORAGE_PATH=./uploads
# Tamano maximo de archivo (20MB en bytes - para radiografias)
MAX_FILE_SIZE=20971520
# Tipos permitidos (incluye DICOM para imagenes medicas)
ALLOWED_FILE_TYPES=image/jpeg,image/png,image/dicom,application/pdf,application/dicom
# Directorio para radiografias
XRAY_STORAGE_PATH=./uploads/radiografias
# =============================================================================
# AWS S3 (para produccion)
# =============================================================================
# AWS_ACCESS_KEY_ID=
# AWS_SECRET_ACCESS_KEY=
# AWS_REGION=us-east-1
# AWS_S3_BUCKET=clinica-dental-uploads
# AWS_S3_XRAY_BUCKET=clinica-dental-radiografias
# =============================================================================
# EMAIL - SMTP
# =============================================================================
# MailHog para desarrollo: puerto 1025
# Servidor real para produccion
# =============================================================================
SMTP_HOST=localhost
SMTP_PORT=1025
SMTP_SECURE=false
# Credenciales (para produccion)
# SMTP_USER=
# SMTP_PASSWORD=
# Remitente por defecto
SMTP_FROM_NAME=Clinica Dental
SMTP_FROM_EMAIL=noreply@clinica-dental.local
# =============================================================================
# SEGURIDAD ADICIONAL
# =============================================================================
# Rate limiting
RATE_LIMIT_WINDOW=900000
RATE_LIMIT_MAX=100
# Helmet (headers de seguridad)
HELMET_ENABLED=true
# CSRF Protection
CSRF_ENABLED=false
# Throttle por IP
THROTTLE_TTL=60
THROTTLE_LIMIT=10
# =============================================================================
# MONITOREO Y METRICAS
# =============================================================================
# Health check endpoint
HEALTH_CHECK_ENABLED=true
# Metricas Prometheus (opcional)
# METRICS_ENABLED=false
# METRICS_PORT=9090
# Sentry (opcional)
# SENTRY_DSN=
# =============================================================================
# CONFIGURACION ESPECIFICA DENTAL
# =============================================================================
# Nomenclatura dental (FDI por defecto)
DENTAL_FDI_NOTATION=true
# Version del formato de odontograma
ODONTOGRAM_VERSION=2.0
# Recordatorios de citas (dias antes)
APPOINTMENT_REMINDER_DAYS=2
# Validez de presupuestos (dias)
BUDGET_VALIDITY_DAYS=30
# Tipos de radiografias habilitados
XRAY_TYPES=periapical,panoramica,oclusal,bitewing,cefalometrica
# =============================================================================
# CUMPLIMIENTO NORMATIVO (NOM-024-SSA3-2012)
# =============================================================================
# Habilitar auditoria (obligatorio en produccion)
AUDIT_ENABLED=true
# Retencion de logs de auditoria (dias)
AUDIT_RETENTION_DAYS=1825
# Encriptacion de datos sensibles
DATA_ENCRYPTION=false
# Firma electronica de expedientes
ELECTRONIC_SIGNATURE=false
# =============================================================================
# DESARROLLO Y DEBUG
# =============================================================================
# Habilitar debug de TypeORM
# TYPEORM_LOGGING=true
# Swagger UI
SWAGGER_ENABLED=true
SWAGGER_TITLE=Clinica Dental API
SWAGGER_VERSION=1.0.0
# Hot reload
HOT_RELOAD=true
# =============================================================================
# PRODUCCION
# =============================================================================
# Estas variables deben configurarse via secrets manager en produccion:
#
# - DB_PASSWORD (secreto)
# - JWT_SECRET (secreto)
# - REDIS_PASSWORD (secreto)
# - AWS_ACCESS_KEY_ID (si usa S3)
# - AWS_SECRET_ACCESS_KEY (si usa S3)
# - SMTP_USER (si usa email)
# - SMTP_PASSWORD (si usa email)
# - SENTRY_DSN (si usa Sentry)
# - ENCRYPTION_KEY (para datos sensibles)
#
# Diferencias de configuracion en produccion:
# - NODE_ENV=production
# - LOG_LEVEL=info
# - LOG_FORMAT=json
# - DB_PORT=5432 (estandar)
# - DB_SSL=true
# - REDIS_PORT=6379 (estandar)
# - STORAGE_TYPE=s3
# - SWAGGER_ENABLED=false
# - HOT_RELOAD=false
# - AUDIT_ENABLED=true
# - DATA_ENCRYPTION=true
# - ELECTRONIC_SIGNATURE=true
#
# IMPORTANTE: Cumplimiento NOM-024-SSA3-2012
# - Logs de auditoria inmutables
# - Retencion minima 5 anos
# - Backups diarios
# =============================================================================
# =============================================================================
# REFERENCIAS
# =============================================================================
# Inventario de entorno: orchestration/environment/ENVIRONMENT-INVENTORY.yml
# Inventario de puertos: orchestration/inventarios/DEVENV-PORTS-INVENTORY.yml
# Perfil DevEnv: orchestration/agents/perfiles/PERFIL-DEVENV.md
# Nomenclatura FDI: https://www.fdiworlddental.org/tooth-numbering-system
# =============================================================================

20
.env.ports Normal file
View File

@ -0,0 +1,20 @@
# =============================================================================
# .env.ports - CLINICA DENTAL
# =============================================================================
# Archivo de referencia de puertos asignados
# Generado por: @PERFIL_DEVENV
# =============================================================================
# Servicios principales
FRONTEND_PORT=3130
BACKEND_PORT=3131
# Base de datos
DB_PORT=5441
# Redis
REDIS_PORT=6388
# =============================================================================
# Referencia: DEVENV-PORTS-INVENTORY.yml
# =============================================================================

81
README.md Normal file
View File

@ -0,0 +1,81 @@
# Clinica Dental - ERP Especializado
**Version:** 0.1.0
**Estado:** Desarrollo
**Tipo:** VERTICAL (erp-clinicas)
**Sistema:** SIMCO + NEXUS v3.4
---
## Descripcion
Sistema de gestion integral para clinicas dentales. Vertical especializada basada en erp-clinicas.
### Funcionalidades Principales
- Gestion de pacientes con expedientes y odontograma digital
- Consultas dentales: diagnostico y tratamientos
- Control de ortodoncia y protesis
- Presupuestos y planes de tratamiento
- Inventario de materiales dentales
- Facturacion de servicios
---
## Stack Tecnologico
| Capa | Tecnologia |
|------|------------|
| Database | PostgreSQL 16+ con RLS |
| Backend | (pendiente) Express.js / NestJS |
| Frontend | (pendiente) React + Vite |
---
## Estructura del Proyecto
```
clinica-dental/
├── database/
│ ├── schemas/ # DDL especifico dental
│ └── seeds/ # Datos iniciales
├── docs/
│ └── 00-vision-general/
├── orchestration/
│ ├── 00-guidelines/
│ ├── environment/
│ ├── inventarios/
│ └── trazas/
└── README.md
```
---
## Herencia
Este proyecto hereda de:
- **erp-clinicas** (modulos base de clinicas)
- **erp-core** (modulos genericos ERP)
---
## Inicio Rapido
```bash
# Database (requiere PostgreSQL y erp-clinicas cargado)
psql -d erp_clinicas -f database/schemas/01-dental-schema-ddl.sql
psql -d erp_clinicas -f database/seeds/fase8/01-dental-catalogos.sql
```
---
## Referencias
- Contexto: `orchestration/00-guidelines/CONTEXTO-PROYECTO.md`
- Herencia: `orchestration/00-guidelines/HERENCIA-ERP-CLINICAS.md`
- Inventario: `orchestration/inventarios/MASTER_INVENTORY.yml`
---
**Creado:** 2026-01-04
**Actualizado:** 2026-01-07

View File

@ -0,0 +1,502 @@
-- ============================================================================
-- DENTAL SCHEMA - Especialización de ERP-Clínicas
-- Clínica Dental
-- ============================================================================
-- Fecha: 2026-01-04
-- Versión: 1.0
-- Hereda de: erp-clinicas FASE-8
-- ============================================================================
-- Schema
CREATE SCHEMA IF NOT EXISTS dental;
-- ============================================================================
-- ENUMS
-- ============================================================================
DO $$ BEGIN
CREATE TYPE dental.estado_pieza AS ENUM (
'sano', 'caries', 'obturacion', 'endodoncia', 'corona',
'puente', 'implante', 'ausente', 'extraccion_indicada',
'diente_temporal', 'fractura', 'movilidad'
);
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;
DO $$ BEGIN
CREATE TYPE dental.cara_dental AS ENUM (
'mesial', 'distal', 'oclusal', 'incisal',
'vestibular', 'bucal', 'lingual', 'palatino'
);
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;
DO $$ BEGIN
CREATE TYPE dental.estado_tratamiento AS ENUM (
'pendiente', 'en_proceso', 'completado', 'cancelado'
);
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;
DO $$ BEGIN
CREATE TYPE dental.tipo_ortodoncia AS ENUM (
'brackets_metalicos', 'brackets_esteticos', 'brackets_linguales',
'alineadores', 'removible', 'retenedor'
);
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;
-- ============================================================================
-- CATÁLOGOS
-- ============================================================================
-- Piezas dentales
CREATE TABLE IF NOT EXISTS dental.piezas_dentales (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
numero VARCHAR(10) NOT NULL UNIQUE, -- '11', '12', ... '48', '51'...'85'
nombre VARCHAR(50) NOT NULL,
cuadrante INTEGER NOT NULL CHECK (cuadrante BETWEEN 1 AND 8),
es_temporal BOOLEAN DEFAULT false,
descripcion TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE dental.piezas_dentales IS 'Catálogo de piezas dentales (nomenclatura FDI)';
-- Tratamientos dentales
CREATE TABLE IF NOT EXISTS dental.tratamientos_catalogo (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
codigo VARCHAR(20) NOT NULL,
nombre VARCHAR(100) NOT NULL,
categoria VARCHAR(50), -- 'prevencion', 'restauracion', 'endodoncia', etc.
descripcion TEXT,
duracion_minutos INTEGER DEFAULT 30,
precio_base NUMERIC(10,2),
requiere_rx BOOLEAN DEFAULT false,
requiere_anestesia BOOLEAN DEFAULT false,
active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT NOW(),
CONSTRAINT uq_tratamientos_tenant_codigo UNIQUE(tenant_id, codigo)
);
COMMENT ON TABLE dental.tratamientos_catalogo IS 'Catálogo de tratamientos dentales';
-- ============================================================================
-- TABLAS PRINCIPALES
-- ============================================================================
-- Odontograma
CREATE TABLE IF NOT EXISTS dental.odontogramas (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
patient_id UUID NOT NULL, -- Referencia a clinica.patients
fecha_creacion DATE NOT NULL DEFAULT CURRENT_DATE,
fecha_actualizacion DATE,
notas TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE dental.odontogramas IS 'Odontogramas de pacientes';
-- Estado de piezas dentales por odontograma
CREATE TABLE IF NOT EXISTS dental.odontograma_piezas (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
odontograma_id UUID NOT NULL REFERENCES dental.odontogramas(id) ON DELETE CASCADE,
pieza_id UUID NOT NULL REFERENCES dental.piezas_dentales(id),
-- Estado general
estado dental.estado_pieza DEFAULT 'sano',
-- Estados por cara (JSONB para flexibilidad)
caras_afectadas JSONB, -- {"mesial": "caries", "oclusal": "obturacion"}
-- Notas
observaciones TEXT,
-- Control
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
CONSTRAINT uq_odontograma_pieza UNIQUE(odontograma_id, pieza_id)
);
COMMENT ON TABLE dental.odontograma_piezas IS 'Estado de cada pieza dental en el odontograma';
-- Tratamientos de paciente
CREATE TABLE IF NOT EXISTS dental.tratamientos_paciente (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
patient_id UUID NOT NULL,
odontograma_id UUID REFERENCES dental.odontogramas(id),
tratamiento_id UUID REFERENCES dental.tratamientos_catalogo(id),
odontologo_id UUID, -- Referencia a clinica.doctors
consultation_id UUID, -- Referencia a clinica.consultations
-- Pieza(s) tratada(s)
pieza_id UUID REFERENCES dental.piezas_dentales(id),
caras_tratadas dental.cara_dental[],
-- Datos del tratamiento
fecha_inicio DATE NOT NULL DEFAULT CURRENT_DATE,
fecha_fin DATE,
estado dental.estado_tratamiento DEFAULT 'pendiente',
-- Costo
precio NUMERIC(10,2),
descuento NUMERIC(5,2) DEFAULT 0,
precio_final NUMERIC(10,2),
-- Notas
notas TEXT,
-- Control
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE dental.tratamientos_paciente IS 'Tratamientos realizados a pacientes';
-- Ortodoncia
CREATE TABLE IF NOT EXISTS dental.ortodoncia (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
patient_id UUID NOT NULL,
odontologo_id UUID,
-- Tipo de tratamiento
tipo dental.tipo_ortodoncia NOT NULL,
marca VARCHAR(100),
-- Fechas
fecha_inicio DATE NOT NULL,
fecha_estimada_fin DATE,
fecha_real_fin DATE,
-- Estado
estado dental.estado_tratamiento DEFAULT 'en_proceso',
meses_estimados INTEGER,
-- Costo
costo_total NUMERIC(10,2),
enganche NUMERIC(10,2),
mensualidad NUMERIC(10,2),
-- Notas
notas TEXT,
-- Control
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE dental.ortodoncia IS 'Tratamientos de ortodoncia';
-- Citas de ortodoncia (seguimiento)
CREATE TABLE IF NOT EXISTS dental.ortodoncia_citas (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
ortodoncia_id UUID NOT NULL REFERENCES dental.ortodoncia(id) ON DELETE CASCADE,
appointment_id UUID, -- Referencia a clinica.appointments
-- Datos de la cita
fecha DATE NOT NULL,
numero_cita INTEGER,
-- Procedimiento
procedimiento TEXT,
arco_superior VARCHAR(50),
arco_inferior VARCHAR(50),
ligas VARCHAR(50),
-- Observaciones
observaciones TEXT,
proxima_cita DATE,
-- Control
created_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE dental.ortodoncia_citas IS 'Citas de seguimiento de ortodoncia';
-- Prótesis
CREATE TABLE IF NOT EXISTS dental.protesis (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
patient_id UUID NOT NULL,
odontologo_id UUID,
-- Tipo
tipo VARCHAR(50) NOT NULL, -- 'corona', 'puente', 'parcial', 'total', 'implante'
-- Piezas involucradas
piezas_involucradas TEXT[], -- ['11', '12', '13']
-- Laboratorio
laboratorio_id UUID, -- Referencia a proveedor
fecha_envio_lab DATE,
fecha_recepcion_lab DATE,
-- Material
material VARCHAR(100),
color VARCHAR(50),
-- Estado
estado dental.estado_tratamiento DEFAULT 'en_proceso',
fecha_colocacion DATE,
-- Garantía
tiene_garantia BOOLEAN DEFAULT false,
meses_garantia INTEGER,
-- Costo
costo_laboratorio NUMERIC(10,2),
precio_paciente NUMERIC(10,2),
-- Notas
notas TEXT,
-- Control
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE dental.protesis IS 'Registro de prótesis dentales';
-- Radiografías
CREATE TABLE IF NOT EXISTS dental.radiografias (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
patient_id UUID NOT NULL,
consultation_id UUID,
-- Tipo
tipo VARCHAR(50) NOT NULL, -- 'periapical', 'panoramica', 'cefalometrica', 'oclusal'
pieza_id UUID REFERENCES dental.piezas_dentales(id),
-- Archivo
fecha DATE NOT NULL DEFAULT CURRENT_DATE,
url_imagen VARCHAR(255),
-- Interpretación
interpretacion TEXT,
-- Control
created_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE dental.radiografias IS 'Registro de radiografías dentales';
-- Presupuestos
CREATE TABLE IF NOT EXISTS dental.presupuestos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
patient_id UUID NOT NULL,
odontologo_id UUID,
-- Datos
numero VARCHAR(20),
fecha DATE NOT NULL DEFAULT CURRENT_DATE,
fecha_vencimiento DATE,
-- Estado
estado VARCHAR(20) DEFAULT 'pendiente', -- 'pendiente', 'aprobado', 'rechazado', 'vencido'
-- Totales
subtotal NUMERIC(12,2) DEFAULT 0,
descuento_porcentaje NUMERIC(5,2) DEFAULT 0,
descuento_monto NUMERIC(12,2) DEFAULT 0,
total NUMERIC(12,2) DEFAULT 0,
-- Plan de pago
requiere_financiamiento BOOLEAN DEFAULT false,
enganche NUMERIC(12,2),
numero_pagos INTEGER,
monto_pago NUMERIC(12,2),
-- Notas
notas TEXT,
-- Control
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE dental.presupuestos IS 'Presupuestos de tratamiento';
-- Líneas de presupuesto
CREATE TABLE IF NOT EXISTS dental.presupuesto_lineas (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
presupuesto_id UUID NOT NULL REFERENCES dental.presupuestos(id) ON DELETE CASCADE,
tratamiento_id UUID REFERENCES dental.tratamientos_catalogo(id),
-- Pieza
pieza_id UUID REFERENCES dental.piezas_dentales(id),
descripcion TEXT,
-- Cantidades
cantidad INTEGER DEFAULT 1,
precio_unitario NUMERIC(10,2),
descuento NUMERIC(5,2) DEFAULT 0,
subtotal NUMERIC(10,2),
-- Secuencia
sequence INTEGER DEFAULT 10,
-- Control
created_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE dental.presupuesto_lineas IS 'Líneas de presupuesto';
-- ============================================================================
-- EXTENSIONES A TABLAS DE ERP-CLINICAS
-- ============================================================================
DO $$
BEGIN
-- Extensión a clinica.patients
IF EXISTS (SELECT 1 FROM information_schema.tables
WHERE table_schema = 'clinica' AND table_name = 'patients') THEN
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_schema = 'clinica' AND table_name = 'patients'
AND column_name = 'odontograma_activo_id') THEN
ALTER TABLE clinica.patients ADD COLUMN odontograma_activo_id UUID;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_schema = 'clinica' AND table_name = 'patients'
AND column_name = 'tiene_ortodoncia') THEN
ALTER TABLE clinica.patients ADD COLUMN tiene_ortodoncia BOOLEAN DEFAULT false;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_schema = 'clinica' AND table_name = 'patients'
AND column_name = 'tiene_protesis') THEN
ALTER TABLE clinica.patients ADD COLUMN tiene_protesis BOOLEAN DEFAULT false;
END IF;
END IF;
END $$;
-- ============================================================================
-- SEED: Piezas dentales (catálogo global)
-- ============================================================================
INSERT INTO dental.piezas_dentales (numero, nombre, cuadrante, es_temporal) VALUES
-- Cuadrante 1 - Superior derecho (permanentes)
('18', 'Tercer molar superior derecho', 1, false),
('17', 'Segundo molar superior derecho', 1, false),
('16', 'Primer molar superior derecho', 1, false),
('15', 'Segundo premolar superior derecho', 1, false),
('14', 'Primer premolar superior derecho', 1, false),
('13', 'Canino superior derecho', 1, false),
('12', 'Incisivo lateral superior derecho', 1, false),
('11', 'Incisivo central superior derecho', 1, false),
-- Cuadrante 2 - Superior izquierdo (permanentes)
('21', 'Incisivo central superior izquierdo', 2, false),
('22', 'Incisivo lateral superior izquierdo', 2, false),
('23', 'Canino superior izquierdo', 2, false),
('24', 'Primer premolar superior izquierdo', 2, false),
('25', 'Segundo premolar superior izquierdo', 2, false),
('26', 'Primer molar superior izquierdo', 2, false),
('27', 'Segundo molar superior izquierdo', 2, false),
('28', 'Tercer molar superior izquierdo', 2, false),
-- Cuadrante 3 - Inferior izquierdo (permanentes)
('31', 'Incisivo central inferior izquierdo', 3, false),
('32', 'Incisivo lateral inferior izquierdo', 3, false),
('33', 'Canino inferior izquierdo', 3, false),
('34', 'Primer premolar inferior izquierdo', 3, false),
('35', 'Segundo premolar inferior izquierdo', 3, false),
('36', 'Primer molar inferior izquierdo', 3, false),
('37', 'Segundo molar inferior izquierdo', 3, false),
('38', 'Tercer molar inferior izquierdo', 3, false),
-- Cuadrante 4 - Inferior derecho (permanentes)
('41', 'Incisivo central inferior derecho', 4, false),
('42', 'Incisivo lateral inferior derecho', 4, false),
('43', 'Canino inferior derecho', 4, false),
('44', 'Primer premolar inferior derecho', 4, false),
('45', 'Segundo premolar inferior derecho', 4, false),
('46', 'Primer molar inferior derecho', 4, false),
('47', 'Segundo molar inferior derecho', 4, false),
('48', 'Tercer molar inferior derecho', 4, false),
-- Cuadrante 5 - Superior derecho (temporales)
('55', 'Segundo molar temporal superior derecho', 5, true),
('54', 'Primer molar temporal superior derecho', 5, true),
('53', 'Canino temporal superior derecho', 5, true),
('52', 'Incisivo lateral temporal superior derecho', 5, true),
('51', 'Incisivo central temporal superior derecho', 5, true),
-- Cuadrante 6 - Superior izquierdo (temporales)
('61', 'Incisivo central temporal superior izquierdo', 6, true),
('62', 'Incisivo lateral temporal superior izquierdo', 6, true),
('63', 'Canino temporal superior izquierdo', 6, true),
('64', 'Primer molar temporal superior izquierdo', 6, true),
('65', 'Segundo molar temporal superior izquierdo', 6, true),
-- Cuadrante 7 - Inferior izquierdo (temporales)
('71', 'Incisivo central temporal inferior izquierdo', 7, true),
('72', 'Incisivo lateral temporal inferior izquierdo', 7, true),
('73', 'Canino temporal inferior izquierdo', 7, true),
('74', 'Primer molar temporal inferior izquierdo', 7, true),
('75', 'Segundo molar temporal inferior izquierdo', 7, true),
-- Cuadrante 8 - Inferior derecho (temporales)
('81', 'Incisivo central temporal inferior derecho', 8, true),
('82', 'Incisivo lateral temporal inferior derecho', 8, true),
('83', 'Canino temporal inferior derecho', 8, true),
('84', 'Primer molar temporal inferior derecho', 8, true),
('85', 'Segundo molar temporal inferior derecho', 8, true)
ON CONFLICT (numero) DO NOTHING;
-- ============================================================================
-- ÍNDICES
-- ============================================================================
CREATE INDEX IF NOT EXISTS idx_tratamientos_catalogo_tenant ON dental.tratamientos_catalogo(tenant_id);
CREATE INDEX IF NOT EXISTS idx_tratamientos_catalogo_categoria ON dental.tratamientos_catalogo(tenant_id, categoria);
CREATE INDEX IF NOT EXISTS idx_odontogramas_tenant ON dental.odontogramas(tenant_id);
CREATE INDEX IF NOT EXISTS idx_odontogramas_patient ON dental.odontogramas(patient_id);
CREATE INDEX IF NOT EXISTS idx_odontograma_piezas_odontograma ON dental.odontograma_piezas(odontograma_id);
CREATE INDEX IF NOT EXISTS idx_odontograma_piezas_pieza ON dental.odontograma_piezas(pieza_id);
CREATE INDEX IF NOT EXISTS idx_tratamientos_paciente_tenant ON dental.tratamientos_paciente(tenant_id);
CREATE INDEX IF NOT EXISTS idx_tratamientos_paciente_patient ON dental.tratamientos_paciente(patient_id);
CREATE INDEX IF NOT EXISTS idx_tratamientos_paciente_estado ON dental.tratamientos_paciente(tenant_id, estado);
CREATE INDEX IF NOT EXISTS idx_ortodoncia_tenant ON dental.ortodoncia(tenant_id);
CREATE INDEX IF NOT EXISTS idx_ortodoncia_patient ON dental.ortodoncia(patient_id);
CREATE INDEX IF NOT EXISTS idx_ortodoncia_estado ON dental.ortodoncia(tenant_id, estado);
CREATE INDEX IF NOT EXISTS idx_ortodoncia_citas_ortodoncia ON dental.ortodoncia_citas(ortodoncia_id);
CREATE INDEX IF NOT EXISTS idx_protesis_tenant ON dental.protesis(tenant_id);
CREATE INDEX IF NOT EXISTS idx_protesis_patient ON dental.protesis(patient_id);
CREATE INDEX IF NOT EXISTS idx_radiografias_tenant ON dental.radiografias(tenant_id);
CREATE INDEX IF NOT EXISTS idx_radiografias_patient ON dental.radiografias(patient_id);
CREATE INDEX IF NOT EXISTS idx_presupuestos_tenant ON dental.presupuestos(tenant_id);
CREATE INDEX IF NOT EXISTS idx_presupuestos_patient ON dental.presupuestos(patient_id);
CREATE INDEX IF NOT EXISTS idx_presupuestos_estado ON dental.presupuestos(tenant_id, estado);
CREATE INDEX IF NOT EXISTS idx_presupuesto_lineas_presupuesto ON dental.presupuesto_lineas(presupuesto_id);
-- ============================================================================
-- RLS
-- ============================================================================
ALTER TABLE dental.tratamientos_catalogo ENABLE ROW LEVEL SECURITY;
ALTER TABLE dental.odontogramas ENABLE ROW LEVEL SECURITY;
ALTER TABLE dental.odontograma_piezas ENABLE ROW LEVEL SECURITY;
ALTER TABLE dental.tratamientos_paciente ENABLE ROW LEVEL SECURITY;
ALTER TABLE dental.ortodoncia ENABLE ROW LEVEL SECURITY;
ALTER TABLE dental.ortodoncia_citas ENABLE ROW LEVEL SECURITY;
ALTER TABLE dental.protesis ENABLE ROW LEVEL SECURITY;
ALTER TABLE dental.radiografias ENABLE ROW LEVEL SECURITY;
ALTER TABLE dental.presupuestos ENABLE ROW LEVEL SECURITY;
ALTER TABLE dental.presupuesto_lineas ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_tratamientos_cat ON dental.tratamientos_catalogo;
CREATE POLICY tenant_isolation_tratamientos_cat ON dental.tratamientos_catalogo
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
DROP POLICY IF EXISTS tenant_isolation_odontogramas ON dental.odontogramas;
CREATE POLICY tenant_isolation_odontogramas ON dental.odontogramas
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
DROP POLICY IF EXISTS tenant_isolation_odontograma_piezas ON dental.odontograma_piezas;
CREATE POLICY tenant_isolation_odontograma_piezas ON dental.odontograma_piezas
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
DROP POLICY IF EXISTS tenant_isolation_tratamientos_pac ON dental.tratamientos_paciente;
CREATE POLICY tenant_isolation_tratamientos_pac ON dental.tratamientos_paciente
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
DROP POLICY IF EXISTS tenant_isolation_ortodoncia ON dental.ortodoncia;
CREATE POLICY tenant_isolation_ortodoncia ON dental.ortodoncia
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
DROP POLICY IF EXISTS tenant_isolation_ortodoncia_citas ON dental.ortodoncia_citas;
CREATE POLICY tenant_isolation_ortodoncia_citas ON dental.ortodoncia_citas
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
DROP POLICY IF EXISTS tenant_isolation_protesis ON dental.protesis;
CREATE POLICY tenant_isolation_protesis ON dental.protesis
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
DROP POLICY IF EXISTS tenant_isolation_radiografias ON dental.radiografias;
CREATE POLICY tenant_isolation_radiografias ON dental.radiografias
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
DROP POLICY IF EXISTS tenant_isolation_presupuestos ON dental.presupuestos;
CREATE POLICY tenant_isolation_presupuestos ON dental.presupuestos
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
DROP POLICY IF EXISTS tenant_isolation_presupuesto_lineas ON dental.presupuesto_lineas;
CREATE POLICY tenant_isolation_presupuesto_lineas ON dental.presupuesto_lineas
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
-- ============================================================================
-- FIN DENTAL SCHEMA
-- ============================================================================

View File

@ -0,0 +1,101 @@
-- ============================================================================
-- SEED DATA: Catálogos de Clínica Dental
-- Especialización de ERP-Clínicas
-- ============================================================================
-- NOTA: Ejecutar después de SET app.current_tenant_id = 'UUID-DEL-TENANT';
-- ============================================================================
-- Tratamientos dentales
INSERT INTO dental.tratamientos_catalogo (tenant_id, codigo, nombre, categoria, duracion_minutos, precio_base, requiere_rx, requiere_anestesia)
SELECT current_setting('app.current_tenant_id', true)::UUID, codigo, nombre, categoria, duracion, precio, rx, anestesia
FROM (VALUES
-- Prevención
('PREV-001', 'Limpieza dental básica', 'prevencion', 45, 600.00, false, false),
('PREV-002', 'Limpieza dental profunda', 'prevencion', 60, 1200.00, false, true),
('PREV-003', 'Aplicación de flúor', 'prevencion', 15, 300.00, false, false),
('PREV-004', 'Sellador de fosetas', 'prevencion', 20, 400.00, false, false),
-- Restauración
('REST-001', 'Resina simple (1 cara)', 'restauracion', 30, 800.00, true, true),
('REST-002', 'Resina compuesta (2 caras)', 'restauracion', 45, 1000.00, true, true),
('REST-003', 'Resina compleja (3+ caras)', 'restauracion', 60, 1300.00, true, true),
('REST-004', 'Incrustación de resina', 'restauracion', 90, 2500.00, true, true),
('REST-005', 'Incrustación de porcelana', 'restauracion', 90, 4000.00, true, true),
-- Endodoncia
('ENDO-001', 'Endodoncia unirradicular', 'endodoncia', 60, 3000.00, true, true),
('ENDO-002', 'Endodoncia birradicular', 'endodoncia', 90, 4000.00, true, true),
('ENDO-003', 'Endodoncia multirradicular', 'endodoncia', 120, 5000.00, true, true),
('ENDO-004', 'Retratamiento endodóntico', 'endodoncia', 120, 5500.00, true, true),
-- Periodoncia
('PERIO-001', 'Raspado y alisado radicular (cuadrante)', 'periodoncia', 60, 1500.00, true, true),
('PERIO-002', 'Cirugía periodontal', 'periodoncia', 120, 6000.00, true, true),
-- Cirugía
('CIRUG-001', 'Extracción simple', 'cirugia', 30, 800.00, true, true),
('CIRUG-002', 'Extracción de tercer molar', 'cirugia', 60, 3500.00, true, true),
('CIRUG-003', 'Extracción quirúrgica compleja', 'cirugia', 90, 5000.00, true, true),
-- Prótesis
('PROT-001', 'Corona de porcelana', 'protesis', 60, 6000.00, true, true),
('PROT-002', 'Corona de zirconia', 'protesis', 60, 8000.00, true, true),
('PROT-003', 'Puente fijo (3 unidades)', 'protesis', 120, 18000.00, true, true),
('PROT-004', 'Prótesis parcial removible', 'protesis', 120, 8000.00, true, false),
('PROT-005', 'Prótesis total', 'protesis', 180, 12000.00, true, false),
-- Implantes
('IMPL-001', 'Implante dental (sin corona)', 'implantes', 90, 15000.00, true, true),
('IMPL-002', 'Corona sobre implante', 'implantes', 60, 8000.00, false, false),
-- Ortodoncia
('ORTO-001', 'Brackets metálicos (tratamiento completo)', 'ortodoncia', 60, 35000.00, true, false),
('ORTO-002', 'Brackets estéticos (tratamiento completo)', 'ortodoncia', 60, 45000.00, true, false),
('ORTO-003', 'Alineadores invisibles', 'ortodoncia', 45, 60000.00, true, false),
('ORTO-004', 'Control mensual ortodoncia', 'ortodoncia', 30, 800.00, false, false),
('ORTO-005', 'Retenedor fijo', 'ortodoncia', 45, 3000.00, false, false),
-- Estética
('ESTE-001', 'Blanqueamiento en consultorio', 'estetica', 90, 5000.00, false, false),
('ESTE-002', 'Blanqueamiento casero', 'estetica', 30, 3000.00, false, false),
('ESTE-003', 'Carilla de resina', 'estetica', 60, 3500.00, false, false),
('ESTE-004', 'Carilla de porcelana', 'estetica', 60, 8000.00, false, false),
-- Diagnóstico
('DIAG-001', 'Radiografía periapical', 'diagnostico', 5, 100.00, false, false),
('DIAG-002', 'Radiografía panorámica', 'diagnostico', 10, 500.00, false, false),
('DIAG-003', 'Radiografía cefalométrica', 'diagnostico', 10, 400.00, false, false),
('DIAG-004', 'Tomografía dental', 'diagnostico', 15, 1500.00, false, false)
) AS t(codigo, nombre, categoria, duracion, precio, rx, anestesia)
WHERE current_setting('app.current_tenant_id', true) IS NOT NULL
AND current_setting('app.current_tenant_id', true) != ''
ON CONFLICT (tenant_id, codigo) DO NOTHING;
-- Skills específicos dentales
INSERT INTO hr.skills (tenant_id, skill_type_id, name, requiere_cedula)
SELECT
current_setting('app.current_tenant_id', true)::UUID,
st.id,
unnest(ARRAY[
'Odontología General',
'Ortodoncia',
'Endodoncia',
'Periodoncia',
'Cirugía Maxilofacial',
'Odontopediatría',
'Prostodoncia',
'Implantología',
'Estética Dental',
'Rehabilitación Oral'
]),
true
FROM hr.skill_types st
WHERE st.name = 'Especialidad Médica'
AND st.tenant_id = current_setting('app.current_tenant_id', true)::UUID
ON CONFLICT DO NOTHING;
-- Ubicaciones (unidades dentales)
INSERT INTO hr.work_locations (tenant_id, name, tipo_consultorio, capacidad, equipamiento)
SELECT current_setting('app.current_tenant_id', true)::UUID, name, tipo, capacidad, equipamiento::TEXT[]
FROM (VALUES
('Unidad Dental 1', 'especialidad', 1, ARRAY['sillon', 'rayos_x', 'ultrasonido']),
('Unidad Dental 2', 'especialidad', 1, ARRAY['sillon', 'rayos_x', 'ultrasonido']),
('Unidad Dental 3', 'especialidad', 1, ARRAY['sillon', 'rayos_x']),
('Quirófano Dental', 'quirofano', 1, ARRAY['sillon', 'rayos_x', 'equipo_cirugia']),
('Sala de Rayos X', 'laboratorio', 2, ARRAY['panoramico', 'cefalometrico']),
('Laboratorio Dental', 'laboratorio', 2, ARRAY['modelos', 'protesis'])
) AS t(name, tipo, capacidad, equipamiento)
WHERE current_setting('app.current_tenant_id', true) IS NOT NULL
AND current_setting('app.current_tenant_id', true) != ''
ON CONFLICT DO NOTHING;

View File

@ -0,0 +1,44 @@
# Vision General - Clinica Dental
## Proposito
Sistema de gestion integral para clinicas dentales que permite:
1. **Gestion de Pacientes**
- Expedientes con historial completo
- Odontograma digital interactivo
- Historial de tratamientos
2. **Consultas Dentales**
- Registro de diagnosticos
- Planes de tratamiento
- Presupuestos detallados
3. **Especialidades**
- Ortodoncia (brackets, alineadores)
- Endodoncia (tratamientos de conductos)
- Protesis (coronas, puentes, dentaduras)
- Cirugia (extracciones, implantes)
4. **Operaciones**
- Inventario de materiales
- Facturacion de servicios
- Agenda de citas
## Usuarios
| Rol | Acceso |
|-----|--------|
| Odontologo | Consultas, diagnosticos, tratamientos |
| Auxiliar dental | Apoyo en procedimientos |
| Recepcionista | Citas, cobros |
| Administrador | Gestion completa |
## Alcance
- **Incluido:** Gestion clinica, odontograma, tratamientos, facturacion
- **Excluido:** Contabilidad avanzada (usa erp-core), nomina
## Referencias
Ver `orchestration/00-guidelines/CONTEXTO-PROYECTO.md` para detalles completos del negocio.

View File

@ -0,0 +1,162 @@
# Contexto del Proyecto - Clínica Dental
## 1. Información General
| Campo | Valor |
|-------|-------|
| **Nombre:** | Clínica Dental |
| **Tipo:** | ERP Especializado |
| **Giro:** | Servicios Odontológicos |
| **Base:** | erp-clinicas |
| **Fecha creación:** | 2026-01-04 |
---
## 2. Descripción del Negocio
Sistema de gestión integral para clínicas dentales que incluye:
- **Gestión de pacientes:** Expedientes con odontograma
- **Consultas dentales:** Diagnóstico, tratamientos
- **Odontograma digital:** Estado de cada pieza dental
- **Tratamientos:** Seguimiento de procedimientos
- **Ortodoncia:** Control de tratamientos ortodónticos
- **Prótesis:** Registro de trabajos protésicos
- **Presupuestos:** Planes de tratamiento con costos
- **Inventario:** Materiales dentales
- **Facturación:** Cobro de servicios
## 3. Usuarios del Sistema
| Rol | Funciones |
|-----|-----------|
| Odontólogo | Consultas, diagnósticos, tratamientos |
| Auxiliar dental | Apoyo en procedimientos |
| Recepcionista | Citas, cobros |
| Higienista | Limpiezas, profilaxis |
| Técnico dental | Elaboración de prótesis |
| Administrador | Gestión general |
## 4. Procesos Principales
### 4.1 Flujo de Consulta Dental
```
1. Paciente llega / se verifica cita
2. Recepción registra llegada
3. Revisión de odontograma previo
4. Odontólogo realiza exploración
5. Actualización de odontograma
6. Diagnóstico y plan de tratamiento
7. Presupuesto (si es necesario)
8. Procedimiento (si aplica)
9. Próxima cita
10. Cobro en recepción
```
### 4.2 Flujo de Ortodoncia
```
1. Consulta de valoración
2. Estudios (Rx, fotos, modelos)
3. Plan de tratamiento
4. Presupuesto y financiamiento
5. Colocación de aparatología
6. Citas de control (mensual)
7. Retiro de aparatología
8. Colocación de retenedores
9. Citas de revisión
```
## 5. Entidades Principales
### 5.1 Odontograma
El odontograma es el registro gráfico del estado dental:
| Campo | Descripción |
|-------|-------------|
| Pieza | Número de diente (1-32 o deciduos) |
| Estado | Sano, caries, extracción, etc. |
| Caras afectadas | Mesial, Distal, Oclusal, etc. |
| Tratamientos | Historial de procedimientos |
### 5.2 Nomenclatura Dental
**Sistema FDI (dos dígitos):**
- Cuadrante 1: Superior derecho (11-18)
- Cuadrante 2: Superior izquierdo (21-28)
- Cuadrante 3: Inferior izquierdo (31-38)
- Cuadrante 4: Inferior derecho (41-48)
**Dientes deciduos:**
- Cuadrantes 5-8 (51-55, 61-65, 71-75, 81-85)
### 5.3 Tratamientos Comunes
| Categoría | Tratamientos |
|-----------|-------------|
| Prevención | Limpieza, selladores, fluoruro |
| Restauración | Resinas, amalgamas, incrustaciones |
| Endodoncia | Tratamiento de conductos |
| Periodoncia | Raspados, cirugía periodontal |
| Cirugía | Extracciones, implantes |
| Prótesis | Coronas, puentes, dentaduras |
| Ortodoncia | Brackets, alineadores |
| Estética | Blanqueamiento, carillas |
## 6. Catálogos Específicos
### 6.1 Especialidades Odontológicas
- Odontología General
- Ortodoncia
- Endodoncia
- Periodoncia
- Cirugía Maxilofacial
- Odontopediatría
- Prostodoncia
- Estética Dental
- Implantología
### 6.2 Estados de Piezas Dentales
- Sano
- Caries
- Obturación (resina/amalgama)
- Endodoncia
- Corona
- Puente
- Implante
- Ausente
- Extracción indicada
### 6.3 Caras Dentales
- Mesial (M)
- Distal (D)
- Oclusal/Incisal (O/I)
- Vestibular/Bucal (V/B)
- Lingual/Palatino (L/P)
## 7. Integraciones
| Sistema | Propósito |
|---------|-----------|
| Radiografías digitales | Captura de Rx periapicales, panorámicas |
| Laboratorio dental | Pedidos de prótesis |
| Proveedores | Materiales dentales |
## 8. Métricas Clave
| Métrica | Descripción |
|---------|-------------|
| Consultas/día | Número de pacientes atendidos |
| Tratamientos completados | Planes terminados |
| Tasa retención ortodoncia | Pacientes que completan tratamiento |
| Ticket promedio | Ingreso por paciente |
| Ocupación unidades | Uso de sillones dentales |
---
**Última actualización:** 2026-01-04

View File

@ -0,0 +1,116 @@
# Herencia ERP-Clínicas - Clínica Dental
## Información del Proyecto
| Campo | Valor |
|-------|-------|
| **Proyecto:** | clinica-dental |
| **Hereda de:** | erp-clinicas |
| **Fecha creación:** | 2026-01-04 |
| **Versión ERP-Clínicas:** | 1.0 FASE-8 |
---
## 1. Relación de Herencia
```
erp-core (FASE-8)
└── erp-clinicas (Base Genérica)
└── clinica-dental (Especialización)
```
## 2. Qué Se Hereda de ERP-Clínicas
### 2.1 Schemas y Tablas
| Schema | Tablas | Heredadas |
|--------|--------|-----------|
| clinica | 13 tablas base | ✅ |
| financial | 4 tablas FASE-8 | ✅ |
| hr | 11 tablas FASE-8 | ✅ |
| inventory | 5 tablas FASE-8 | ✅ |
| purchase | 1 tabla FASE-8 | ✅ |
### 2.2 Funcionalidades Heredadas
- Sistema de citas y consultas
- Expedientes clínicos
- Gestión de pacientes
- Sistema de prescripciones
- Gestión de personal (odontólogos)
- Inventario de materiales
- Pagos y facturación
## 3. Especializaciones Dentales
### 3.1 Adaptaciones de Terminología
| ERP-Clínicas | Dental |
|--------------|--------|
| Médico | Odontólogo |
| Especialidad Médica | Especialidad Odontológica |
| Consulta | Consulta Dental |
| Receta | Receta Dental |
| Consultorio | Consultorio Dental/Unidad |
### 3.2 Tablas Adicionales
| Tabla | Propósito |
|-------|-----------|
| dental.odontograma | Estado dental del paciente |
| dental.piezas_dentales | Catálogo de piezas dentales |
| dental.tratamientos | Catálogo de tratamientos dentales |
| dental.tratamientos_paciente | Tratamientos realizados |
| dental.ortodoncia | Seguimiento de ortodoncia |
| dental.protesis | Registro de prótesis |
| dental.radiografias | Registro de radiografías |
| dental.presupuestos | Presupuestos de tratamiento |
### 3.3 Campos Adicionales
| Tabla Base | Campos Dental |
|------------|---------------|
| patients | odontograma_id, tiene_ortodoncia, tiene_protesis |
| consultations | tratamiento_id, pieza_dental, procedimiento |
| prescriptions | uso_dental, indicaciones_especiales |
## 4. Normativa Aplicable
| Normativa | Descripción |
|-----------|-------------|
| NOM-013-SSA2-2015 | Prevención y control enfermedades bucales |
| NOM-004-SSA3-2012 | Expediente clínico |
| COFEPRIS | Registro de establecimientos |
## 5. Instalación
### 5.1 Orden de Ejecución
```bash
# 1. Base ERP-Clínicas (heredado)
psql -f erp-clinicas/database/init/01-extensions.sql
psql -f erp-clinicas/database/init/02-core-schema.sql
psql -f erp-clinicas/database/init/03-clinical-tables.sql
psql -f erp-clinicas/database/schemas/04-financial-ext-schema-ddl.sql
psql -f erp-clinicas/database/schemas/05-hr-ext-fase8-schema-ddl.sql
psql -f erp-clinicas/database/schemas/06-inventory-ext-fase8-schema-ddl.sql
psql -f erp-clinicas/database/schemas/07-purchase-ext-fase8-schema-ddl.sql
psql -f erp-clinicas/database/schemas/08-clinica-ext-fase8-schema-ddl.sql
# 2. Especialización Dental
psql -f clinica-dental/database/schemas/01-dental-schema-ddl.sql
# 3. Seeds
psql -f erp-clinicas/database/seeds/fase8/*.sql
psql -f clinica-dental/database/seeds/fase8/*.sql
```
## 6. Versionado
| Versión | Fecha | Cambios |
|---------|-------|---------|
| 1.0 | 2026-01-04 | Creación inicial, herencia de erp-clinicas FASE-8 |
---
**Última actualización:** 2026-01-04

View File

@ -0,0 +1,56 @@
# PROJECT STATUS - Clinica Dental
**Fecha:** 2026-01-07
**Estado:** En Desarrollo
**Fase:** Database
---
## Resumen
| Aspecto | Estado | Notas |
|---------|--------|-------|
| Database | Completado | DDL y seeds listos |
| Backend | Pendiente | - |
| Frontend | Pendiente | - |
| Tests | Pendiente | - |
| Documentacion | Parcial | Contexto completo, falta epicas |
---
## Progreso por Modulo
| Modulo | DDL | Backend | Frontend | Tests |
|--------|-----|---------|----------|-------|
| Odontograma | OK | - | - | - |
| Tratamientos | OK | - | - | - |
| Ortodoncia | OK | - | - | - |
| Protesis | OK | - | - | - |
---
## Dependencias
- **erp-clinicas:** Modulos base de gestion clinica
- **erp-core:** Auth, users, tenants, billing
---
## Proximas Acciones
1. Implementar backend para modulo odontograma
2. Crear componente visual de odontograma
3. Integrar con sistema de citas de erp-clinicas
---
## Riesgos
| Riesgo | Probabilidad | Impacto | Mitigacion |
|--------|--------------|---------|------------|
| Complejidad odontograma UI | Media | Alto | Usar librerias SVG |
| Integracion con erp-clinicas | Baja | Medio | Seguir patrones existentes |
---
**Ultima actualizacion:** 2026-01-07

View File

@ -0,0 +1,804 @@
# =============================================================================
# ENVIRONMENT-INVENTORY.yml - CLINICA-DENTAL
# =============================================================================
# Inventario Completo de Entorno de Desarrollo y Produccion
# Generado por: @PERFIL_DEVENV
# Basado en: orchestration/templates/TEMPLATE-ENVIRONMENT-INVENTORY.yml
# =============================================================================
version: "1.1.0"
fecha_creacion: "2026-01-04"
fecha_actualizacion: "2026-01-04"
responsable: "@PERFIL_DEVENV"
# -----------------------------------------------------------------------------
# IDENTIFICACION DEL PROYECTO
# -----------------------------------------------------------------------------
proyecto:
nombre: "Clinica Dental"
alias: "clinica-dental"
codigo: "CD"
nivel: "NIVEL_2B.3"
tipo: "vertical-especializada"
estado: "desarrollo"
descripcion: "Sistema de gestion para clinicas dentales y odontologicas"
parent: "erp-clinicas"
herencia:
- erp-core
- erp-clinicas
normativas:
- "NOM-024-SSA3-2012 (Expediente clinico electronico)"
- "NOM-013-SSA2-2015 (Prevencion y control enfermedades bucales)"
# -----------------------------------------------------------------------------
# HERRAMIENTAS Y RUNTIME
# -----------------------------------------------------------------------------
herramientas:
runtime:
node:
version: "20.x"
version_minima: "18.x"
requerido: true
notas: "LTS recomendado para NestJS y React"
python:
version: ""
requerido: false
notas: "No requerido para este proyecto"
package_managers:
npm:
version: "10.x"
requerido: true
pnpm:
version: "8.x"
requerido: false
notas: "Alternativa opcional"
build_tools:
- nombre: "Vite"
version: "5.x"
uso: "Frontend build y dev server"
- nombre: "TypeScript"
version: "5.x"
uso: "Compilacion de codigo"
- nombre: "NestJS CLI"
version: "10.x"
uso: "Backend scaffolding y build"
linters:
- nombre: "ESLint"
version: "8.x"
config: ".eslintrc.js"
- nombre: "Prettier"
version: "3.x"
config: ".prettierrc"
testing:
- nombre: "Jest"
version: "29.x"
tipo: "unit backend"
config: "jest.config.js"
- nombre: "Vitest"
version: "1.x"
tipo: "unit frontend"
config: "vitest.config.ts"
- nombre: "Supertest"
version: "6.x"
tipo: "e2e"
config: "jest-e2e.config.js"
# -----------------------------------------------------------------------------
# SERVICIOS Y PUERTOS
# -----------------------------------------------------------------------------
servicios:
frontend:
nombre: "clinica-dental-frontend"
framework: "React"
version: "18.x"
puerto: 3130
comando_dev: "npm run dev"
comando_build: "npm run build"
comando_preview: "npm run preview"
ubicacion: "apps/frontend/"
url_local: "http://localhost:3130"
build_output: "dist/"
backend:
nombre: "clinica-dental-backend"
framework: "NestJS"
version: "10.x"
puerto: 3131
comando_dev: "npm run start:dev"
comando_build: "npm run build"
comando_prod: "npm run start:prod"
ubicacion: "apps/backend/"
url_local: "http://localhost:3131"
api_prefix: "/api/v1"
swagger_url: "http://localhost:3131/api/docs"
# -----------------------------------------------------------------------------
# BASE DE DATOS - CONFIGURACION COMPLETA
# -----------------------------------------------------------------------------
base_de_datos:
principal:
engine: "PostgreSQL"
version: "15"
host_variable: "DB_HOST"
puerto_variable: "DB_PORT"
ambientes:
development:
host: "localhost"
puerto: 5441
nombre: "clinica_dental_dev"
usuario: "dental_dev"
password_ref: "DB_PASSWORD en .env"
ssl: false
pool_size: 10
conexion: "postgresql://dental_dev:{password}@localhost:5441/clinica_dental_dev"
test:
host: "localhost"
puerto: 5441
nombre: "clinica_dental_test"
usuario: "dental_dev"
password_ref: "DB_PASSWORD en .env"
ssl: false
pool_size: 5
conexion: "postgresql://dental_dev:{password}@localhost:5441/clinica_dental_test"
staging:
host: "${DB_HOST}"
puerto: 5432
nombre: "clinica_dental_staging"
usuario: "dental_staging"
password_ref: "DB_PASSWORD en variables de CI/CD"
ssl: true
pool_size: 20
conexion: "postgresql://dental_staging:{password}@${DB_HOST}:5432/clinica_dental_staging?sslmode=require"
production:
host: "${DB_HOST}"
puerto: 5432
nombre: "clinica_dental_prod"
usuario: "dental_prod"
password_ref: "DB_PASSWORD en secrets manager"
ssl: true
pool_size: 50
conexion: "postgresql://dental_prod:{password}@${DB_HOST}:5432/clinica_dental_prod?sslmode=require"
schemas:
- nombre: "public"
descripcion: "Schema principal PostgreSQL"
- nombre: "dental"
descripcion: "Entidades odontologicas (odontograma, piezas, tratamientos, ortodoncia)"
- nombre: "clinical"
descripcion: "Heredado de erp-clinicas (consultorios, citas, historiales)"
- nombre: "financial"
descripcion: "Heredado de erp-core (pagos, facturacion, presupuestos)"
- nombre: "hr"
descripcion: "Heredado de erp-core (empleados, especialidades)"
- nombre: "inventory"
descripcion: "Heredado de erp-core (materiales, insumos dentales)"
scripts_inicializacion:
orden:
- "database/init/00-extensions.sql"
- "database/init/01-schemas.sql"
- "database/schemas/01-dental-schema-ddl.sql"
- "database/seeds/fase8/01-dental-catalogos.sql"
- "database/seeds/fase8/02-piezas-dentales-fdi.sql"
datos_iniciales:
piezas_dentales:
total: 52
nomenclatura: "FDI (Federation Dentaire Internationale)"
cuadrantes:
- id: 1
nombre: "Superior derecho"
piezas: "18-11"
tipo: "permanente"
- id: 2
nombre: "Superior izquierdo"
piezas: "21-28"
tipo: "permanente"
- id: 3
nombre: "Inferior izquierdo"
piezas: "31-38"
tipo: "permanente"
- id: 4
nombre: "Inferior derecho"
piezas: "41-48"
tipo: "permanente"
- id: 5
nombre: "Superior derecho temporal"
piezas: "55-51"
tipo: "temporal"
- id: 6
nombre: "Superior izquierdo temporal"
piezas: "61-65"
tipo: "temporal"
- id: 7
nombre: "Inferior izquierdo temporal"
piezas: "71-75"
tipo: "temporal"
- id: 8
nombre: "Inferior derecho temporal"
piezas: "81-85"
tipo: "temporal"
redis:
host_variable: "REDIS_HOST"
puerto_variable: "REDIS_PORT"
ambientes:
development:
host: "localhost"
puerto: 6388
database: 0
password: ""
conexion: "redis://localhost:6388/0"
production:
host: "${REDIS_HOST}"
puerto: 6379
database: 0
password_ref: "REDIS_PASSWORD en secrets"
conexion: "redis://:${REDIS_PASSWORD}@${REDIS_HOST}:6379/0"
uso:
- "Cache de sesiones"
- "Cache de odontogramas"
- "Rate limiting"
- "Queue de tareas (Bull)"
# -----------------------------------------------------------------------------
# VARIABLES DE ENTORNO - DESARROLLO
# -----------------------------------------------------------------------------
variables_entorno:
archivos:
ejemplo: ".env.example"
desarrollo: ".env"
test: ".env.test"
produccion: ".env.production"
development:
- nombre: "NODE_ENV"
valor: "development"
descripcion: "Ambiente de ejecucion"
requerido: true
sensible: false
- nombre: "APP_NAME"
valor: "clinica-dental"
descripcion: "Nombre de la aplicacion"
requerido: true
sensible: false
- nombre: "APP_VERSION"
valor: "1.0.0"
descripcion: "Version de la aplicacion"
requerido: false
sensible: false
# Puertos
- nombre: "FRONTEND_PORT"
valor: "3130"
descripcion: "Puerto del frontend React"
requerido: true
sensible: false
- nombre: "BACKEND_PORT"
valor: "3131"
descripcion: "Puerto del backend NestJS"
requerido: true
sensible: false
# Base de datos
- nombre: "DB_HOST"
valor: "localhost"
descripcion: "Host de PostgreSQL"
requerido: true
sensible: false
- nombre: "DB_PORT"
valor: "5441"
descripcion: "Puerto de PostgreSQL"
requerido: true
sensible: false
- nombre: "DB_NAME"
valor: "clinica_dental_dev"
descripcion: "Nombre de la base de datos"
requerido: true
sensible: false
- nombre: "DB_USER"
valor: "dental_dev"
descripcion: "Usuario de PostgreSQL"
requerido: true
sensible: false
- nombre: "DB_PASSWORD"
valor: ""
descripcion: "Password de PostgreSQL"
requerido: true
sensible: true
generacion: "openssl rand -base64 32"
- nombre: "DATABASE_URL"
valor: "postgresql://dental_dev:${DB_PASSWORD}@localhost:5441/clinica_dental_dev"
descripcion: "Connection string completo"
requerido: true
sensible: true
# Redis
- nombre: "REDIS_HOST"
valor: "localhost"
descripcion: "Host de Redis"
requerido: true
sensible: false
- nombre: "REDIS_PORT"
valor: "6388"
descripcion: "Puerto de Redis"
requerido: true
sensible: false
- nombre: "REDIS_URL"
valor: "redis://localhost:6388/0"
descripcion: "Connection string de Redis"
requerido: true
sensible: false
# Autenticacion
- nombre: "JWT_SECRET"
valor: ""
descripcion: "Secreto para firmar JWT (min 32 caracteres)"
requerido: true
sensible: true
generacion: "openssl rand -base64 64"
- nombre: "JWT_EXPIRES_IN"
valor: "24h"
descripcion: "Tiempo de expiracion del access token"
requerido: true
sensible: false
- nombre: "JWT_REFRESH_EXPIRES_IN"
valor: "7d"
descripcion: "Tiempo de expiracion del refresh token"
requerido: true
sensible: false
# CORS
- nombre: "FRONTEND_URL"
valor: "http://localhost:3130"
descripcion: "URL del frontend para CORS"
requerido: true
sensible: false
- nombre: "ALLOWED_ORIGINS"
valor: "http://localhost:3130,http://localhost:3131"
descripcion: "Origenes permitidos (comma separated)"
requerido: true
sensible: false
# Logging
- nombre: "LOG_LEVEL"
valor: "debug"
descripcion: "Nivel de logging (debug, info, warn, error)"
requerido: false
sensible: false
- nombre: "LOG_FORMAT"
valor: "pretty"
descripcion: "Formato de logs (pretty, json)"
requerido: false
sensible: false
# File Storage (radiografias, documentos)
- nombre: "STORAGE_TYPE"
valor: "local"
descripcion: "Tipo de storage (local, s3, minio)"
requerido: false
sensible: false
- nombre: "STORAGE_PATH"
valor: "./uploads"
descripcion: "Path para almacenamiento local"
requerido: false
sensible: false
- nombre: "MAX_FILE_SIZE"
valor: "20971520"
descripcion: "Tamano maximo de archivo en bytes (20MB para radiografias)"
requerido: false
sensible: false
- nombre: "ALLOWED_FILE_TYPES"
valor: "image/jpeg,image/png,image/dicom,application/pdf"
descripcion: "Tipos de archivo permitidos"
requerido: false
sensible: false
# Email (opcional)
- nombre: "SMTP_HOST"
valor: "localhost"
descripcion: "Host SMTP para emails"
requerido: false
sensible: false
- nombre: "SMTP_PORT"
valor: "1025"
descripcion: "Puerto SMTP (1025 para MailHog)"
requerido: false
sensible: false
# Configuracion Dental Especifica
- nombre: "DENTAL_FDI_NOTATION"
valor: "true"
descripcion: "Usar notacion FDI para piezas dentales"
requerido: false
sensible: false
- nombre: "ODONTOGRAM_VERSION"
valor: "2.0"
descripcion: "Version del formato de odontograma"
requerido: false
sensible: false
production:
notas: |
En produccion, las siguientes variables deben configurarse
via secrets manager o variables de CI/CD:
- DB_PASSWORD (secreto)
- JWT_SECRET (secreto)
- REDIS_PASSWORD (secreto)
- AWS_ACCESS_KEY_ID (si usa S3)
- AWS_SECRET_ACCESS_KEY (si usa S3)
IMPORTANTE - Cumplimiento Normativo:
- NOM-024-SSA3-2012: Logs de auditoria obligatorios
- Encriptacion de datos sensibles (historiales)
- Backups diarios con retencion minima 5 anos
diferencias:
- nombre: "NODE_ENV"
valor: "production"
- nombre: "LOG_LEVEL"
valor: "info"
- nombre: "LOG_FORMAT"
valor: "json"
- nombre: "DB_PORT"
valor: "5432"
- nombre: "REDIS_PORT"
valor: "6379"
- nombre: "STORAGE_TYPE"
valor: "s3"
- nombre: "AUDIT_ENABLED"
valor: "true"
- nombre: "DATA_ENCRYPTION"
valor: "true"
# -----------------------------------------------------------------------------
# CONTENEDORES DOCKER
# -----------------------------------------------------------------------------
docker:
compose_file: "docker-compose.yml"
compose_dev: "docker-compose.dev.yml"
compose_prod: "docker-compose.prod.yml"
services:
- nombre: "db"
imagen: "postgres:15-alpine"
puerto_host: 5441
puerto_container: 5432
variables:
POSTGRES_DB: "clinica_dental_dev"
POSTGRES_USER: "dental_dev"
POSTGRES_PASSWORD: "${DB_PASSWORD}"
volumes:
- "postgres_data:/var/lib/postgresql/data"
healthcheck: "pg_isready -U dental_dev"
- nombre: "redis"
imagen: "redis:7-alpine"
puerto_host: 6388
puerto_container: 6379
volumes:
- "redis_data:/data"
healthcheck: "redis-cli ping"
- nombre: "mailhog"
imagen: "mailhog/mailhog"
puerto_smtp: 1025
puerto_web: 8025
uso: "Testing de emails en desarrollo"
volumes:
- nombre: "postgres_data"
descripcion: "Datos persistentes de PostgreSQL"
- nombre: "redis_data"
descripcion: "Datos persistentes de Redis"
- nombre: "uploads_data"
descripcion: "Radiografias y documentos"
networks:
- nombre: "clinica_dental_network"
driver: "bridge"
# -----------------------------------------------------------------------------
# MIGRACIONES Y SEEDS
# -----------------------------------------------------------------------------
migraciones:
herramienta: "TypeORM"
directorio: "apps/backend/src/database/migrations"
comandos:
generar: "npm run migration:generate -- -n NombreMigracion"
ejecutar: "npm run migration:run"
revertir: "npm run migration:revert"
mostrar: "npm run migration:show"
seeds:
directorio: "database/seeds"
orden:
- "fase8/01-dental-catalogos.sql"
- "fase8/02-piezas-dentales-fdi.sql"
comandos:
ejecutar: "npm run seed"
desarrollo: "npm run seed:dev"
# -----------------------------------------------------------------------------
# SCRIPTS DE DESARROLLO
# -----------------------------------------------------------------------------
scripts:
setup:
descripcion: "Configurar entorno desde cero"
pasos:
- comando: "npm install"
descripcion: "Instalar dependencias"
- comando: "cp .env.example .env"
descripcion: "Crear archivo de configuracion"
- comando: "docker-compose up -d db redis"
descripcion: "Levantar servicios de infraestructura"
- comando: "npm run db:create"
descripcion: "Crear base de datos"
- comando: "npm run migration:run"
descripcion: "Ejecutar migraciones"
- comando: "npm run seed"
descripcion: "Cargar datos iniciales (incluye 52 piezas FDI)"
desarrollo:
frontend: "cd apps/frontend && npm run dev"
backend: "cd apps/backend && npm run start:dev"
ambos: "npm run dev:all"
docker: "docker-compose up -d"
testing:
unit: "npm run test"
unit_watch: "npm run test:watch"
e2e: "npm run test:e2e"
coverage: "npm run test:cov"
build:
frontend: "cd apps/frontend && npm run build"
backend: "cd apps/backend && npm run build"
docker: "docker-compose -f docker-compose.prod.yml build"
database:
create: "npm run db:create"
drop: "npm run db:drop"
reset: "npm run db:reset"
migrations_run: "npm run migration:run"
migrations_revert: "npm run migration:revert"
seed: "npm run seed"
linting:
lint: "npm run lint"
lint_fix: "npm run lint:fix"
format: "npm run format"
# -----------------------------------------------------------------------------
# INSTRUCCIONES DE SETUP
# -----------------------------------------------------------------------------
setup_instrucciones: |
## Setup del Entorno de Desarrollo - Clinica Dental
### Prerequisitos
- Node.js 20.x (LTS)
- PostgreSQL 15 (o Docker)
- Redis 7 (o Docker)
- npm 10.x
- Git
### Opcion 1: Setup con Docker (Recomendado)
```bash
# 1. Clonar repositorio
git clone <url_repo>
cd clinica-dental
# 2. Instalar dependencias
npm install
# 3. Configurar variables de entorno
cp .env.example .env
# Editar .env - generar passwords seguros:
# openssl rand -base64 32 # para DB_PASSWORD
# openssl rand -base64 64 # para JWT_SECRET
# 4. Levantar infraestructura
docker-compose up -d db redis
# 5. Crear base de datos y ejecutar migraciones
npm run db:create
npm run migration:run
npm run seed # Carga 52 piezas dentales FDI
# 6. Iniciar desarrollo
npm run dev:all
```
### Opcion 2: Setup con PostgreSQL Local
```bash
# 1-3. Igual que arriba
# 4. Crear usuario y base de datos en PostgreSQL
sudo -u postgres psql
CREATE USER dental_dev WITH PASSWORD 'tu_password';
CREATE DATABASE clinica_dental_dev OWNER dental_dev;
GRANT ALL PRIVILEGES ON DATABASE clinica_dental_dev TO dental_dev;
\q
# 5. Configurar Redis local o Docker
docker run -d --name redis-dental -p 6388:6379 redis:7-alpine
# 6-7. Continuar con migraciones y seeds
```
### Verificar Instalacion
- Frontend: http://localhost:3130
- Backend API: http://localhost:3131/api/v1
- Swagger Docs: http://localhost:3131/api/docs
- Health Check: http://localhost:3131/health
### Usuarios de Prueba (despues de seed)
- Admin: admin@clinica-dental.local / Admin123!
- Odontologo: doctor@clinica-dental.local / Doctor123!
- Recepcion: recepcion@clinica-dental.local / Recep123!
### Nomenclatura Dental FDI
El sistema usa la nomenclatura FDI (Federation Dentaire Internationale):
- Cuadrante 1: Superior derecho (18-11)
- Cuadrante 2: Superior izquierdo (21-28)
- Cuadrante 3: Inferior izquierdo (31-38)
- Cuadrante 4: Inferior derecho (41-48)
- Cuadrantes 5-8: Denticion temporal
# -----------------------------------------------------------------------------
# TROUBLESHOOTING
# -----------------------------------------------------------------------------
troubleshooting:
- problema: "Puerto 3130 o 3131 en uso"
solucion: |
Verificar con: lsof -i :3130
Terminar proceso: kill -9 <PID>
O cambiar puertos en .env
- problema: "Error de conexion a PostgreSQL"
solucion: |
1. Verificar que PostgreSQL esta corriendo:
docker-compose ps
# o: systemctl status postgresql
2. Verificar credenciales en .env
3. Verificar que la BD existe:
psql -h localhost -p 5441 -U dental_dev -l
- problema: "Error de conexion a Redis"
solucion: |
1. Verificar que Redis esta corriendo:
docker-compose ps
# o: redis-cli -p 6388 ping
2. Verificar puerto en .env
- problema: "Migraciones fallan"
solucion: |
1. Verificar que la BD existe
2. Verificar permisos del usuario
3. Revisar logs: npm run migration:run --verbose
4. Si es necesario, resetear: npm run db:reset
- problema: "Piezas dentales no cargadas"
solucion: |
Ejecutar seeds manualmente:
npm run seed
Verificar: SELECT COUNT(*) FROM dental.piezas_dentales;
Debe retornar 52 (32 permanentes + 20 temporales)
- problema: "Radiografias no se suben"
solucion: |
1. Verificar STORAGE_PATH existe y tiene permisos
2. Verificar MAX_FILE_SIZE en .env (default 20MB)
3. Verificar ALLOWED_FILE_TYPES incluye el tipo de archivo
- problema: "JWT errors"
solucion: |
Verificar que JWT_SECRET esta configurado (min 32 caracteres)
Generar nuevo: openssl rand -base64 64
- problema: "CORS errors en frontend"
solucion: |
Verificar FRONTEND_URL y ALLOWED_ORIGINS en .env
Deben coincidir con la URL del frontend
# -----------------------------------------------------------------------------
# CONFIGURACION DE PRODUCCION
# -----------------------------------------------------------------------------
produccion:
checklist:
- item: "Variables de entorno configuradas via secrets manager"
- item: "SSL/TLS habilitado para BD y Redis"
- item: "Backups automaticos configurados (retencion 5 anos)"
- item: "Monitoreo y alertas activas"
- item: "Rate limiting configurado"
- item: "CORS restringido a dominios autorizados"
- item: "Logs en formato JSON para agregacion"
- item: "Audit logging habilitado (NOM-024-SSA3-2012)"
- item: "Encriptacion de datos sensibles"
infraestructura_recomendada:
base_de_datos: "AWS RDS PostgreSQL 15 o equivalente"
cache: "AWS ElastiCache Redis o equivalente"
storage: "AWS S3 o equivalente (para radiografias)"
cdn: "CloudFront o equivalente"
ci_cd: "GitHub Actions / GitLab CI"
escalado:
backend_replicas: 2
pool_db_size: 50
redis_maxmemory: "512mb"
storage_bucket_region: "us-east-1"
cumplimiento:
nom_024_ssa3:
descripcion: "Expediente clinico electronico"
requisitos:
- "Logs de auditoria inmutables"
- "Firma electronica de expedientes"
- "Control de versiones de historiales"
retencion_datos:
expedientes: "5 anos minimo"
radiografias: "5 anos minimo"
logs_auditoria: "5 anos"
# -----------------------------------------------------------------------------
# REFERENCIAS
# -----------------------------------------------------------------------------
referencias:
perfil_devenv: "orchestration/agents/perfiles/PERFIL-DEVENV.md"
inventario_master: "orchestration/inventarios/DEVENV-MASTER-INVENTORY.yml"
inventario_puertos: "orchestration/inventarios/DEVENV-PORTS-INVENTORY.yml"
contexto_proyecto: "orchestration/00-guidelines/CONTEXTO-PROYECTO.md"
parent_clinicas: "../erp-clinicas/orchestration/environment/ENVIRONMENT-INVENTORY.yml"
schema_dental: "database/schemas/01-dental-schema-ddl.sql"
nomenclatura_fdi: "https://www.fdiworlddental.org/tooth-numbering-system"
# =============================================================================
# FIN DE INVENTARIO
# =============================================================================

View File

@ -0,0 +1,76 @@
---
# MASTER INVENTORY - Clinica Dental
# Version: 1.0.0
# Ultima actualizacion: 2026-01-07
proyecto: "clinica-dental"
descripcion: "ERP especializado para clinicas dentales"
version: "0.1.0"
estado: "desarrollo"
tipo: "vertical"
base: "erp-clinicas"
progreso:
fase_actual: "Database"
porcentaje: 15
database_completado: true
backend_completado: false
frontend_completado: false
herencia:
vertical_padre: "erp-clinicas"
suite_core: "erp-core"
modulos_heredados:
- "auth"
- "users"
- "tenants"
- "roles"
- "patients"
- "appointments"
- "billing"
modulos_especificos:
- id: "DENTAL-001"
nombre: "odontograma"
descripcion: "Registro grafico del estado dental"
estado: "ddl_completado"
- id: "DENTAL-002"
nombre: "tratamientos-dentales"
descripcion: "Procedimientos odontologicos"
estado: "ddl_completado"
- id: "DENTAL-003"
nombre: "ortodoncia"
descripcion: "Control de tratamientos ortodonticos"
estado: "ddl_completado"
- id: "DENTAL-004"
nombre: "protesis"
descripcion: "Registro de trabajos protesicos"
estado: "ddl_completado"
database:
schema: "dental"
archivo_ddl: "database/schemas/01-dental-schema-ddl.sql"
archivo_seeds: "database/seeds/fase8/01-dental-catalogos.sql"
tablas_especificas:
- "dental_pieces"
- "dental_charts"
- "dental_treatments"
- "orthodontic_cases"
- "prosthetics"
catalogos:
- "especialidades_odontologicas"
- "estados_piezas_dentales"
- "caras_dentales"
- "tipos_tratamiento_dental"
proximas_tareas:
- "Implementar backend modulo odontograma"
- "Crear frontend para odontograma digital"
- "Integracion con erp-clinicas"
ultima_actualizacion: "2026-01-07"
actualizado_por: "Orquestador"

View File

@ -0,0 +1,52 @@
# TRAZA DE TAREAS - DATABASE
**Proyecto:** clinica-dental
**Capa:** Database
**Version:** 1.0.0
---
## HISTORIAL
### [2026-01-04] DENTAL-DDL-001
**Estado:** completado
**Agente:** Database-Agent
**Duracion:** ~2h
#### Descripcion
Creacion del schema dental con tablas especificas para odontologia.
#### Archivos Creados
- `database/schemas/01-dental-schema-ddl.sql`
#### Resultado
Schema dental creado con tablas para odontograma, tratamientos, ortodoncia y protesis.
---
### [2026-01-04] DENTAL-SEEDS-001
**Estado:** completado
**Agente:** Database-Agent
**Duracion:** ~1h
#### Descripcion
Seeds iniciales con catalogos odontologicos.
#### Archivos Creados
- `database/seeds/fase8/01-dental-catalogos.sql`
#### Resultado
Catalogos cargados: especialidades, estados de piezas, caras dentales.
---
## TAREAS PENDIENTES
| ID | Tarea | Prioridad | Dependencias |
|----|-------|-----------|--------------|
| DENTAL-DDL-002 | RLS policies para tablas dental | P1 | - |
| DENTAL-DDL-003 | Funciones de validacion odontograma | P2 | - |
---
**Ultima actualizacion:** 2026-01-07