CoolFace
Apppublic

fmatituy/selectospromanager

sourceHugging Faceupdated 6mo agoView on Hugging Face
0likes
db.py1307 linesDownload Raw Back to database
1import sqlite3
2import hashlib
3import os
4from datetime import datetime
5def get_db_path():
6    # Priority 0: Environment variable
7    env_db = os.getenv("DB_NAME", "pro_manager.db")
8    if not env_db.endswith('.db'): env_db += '.db'
9    
10    # Priority 1: Root directory (standard for HF persistent storage or Docker mounts)
11    root_db = os.path.join(os.getcwd(), env_db)
12    if os.path.exists(root_db):
13        return root_db
14    
15    # Priority 2: Source directory (development default)
16    src_db = os.path.join(os.path.dirname(os.path.abspath(__file__)), env_db)
17    return src_db
18
19DB_PATH = get_db_path()
20
21def hash_password(password: str) -> str:
22    return hashlib.sha256(password.encode()).hexdigest()
23
24def init_db():
25    conn = sqlite3.connect(DB_PATH)
26    # Optimizaciones de velocidad para SQLite
27    conn.execute('PRAGMA journal_mode = WAL')
28    conn.execute('PRAGMA synchronous = NORMAL')
29    conn.execute('PRAGMA cache_size = -10000') # 10MB approx
30    c = conn.cursor()
31    
32    # Roles y Usuarios
33    c.execute('''
34        CREATE TABLE IF NOT EXISTS roles (
35            id INTEGER PRIMARY KEY AUTOINCREMENT,
36            nombre TEXT UNIQUE
37        )
38    ''')
39    
40    c.execute('''
41        CREATE TABLE IF NOT EXISTS usuarios (
42            id INTEGER PRIMARY KEY AUTOINCREMENT,
43            username TEXT UNIQUE,
44            password TEXT,
45            rol_id INTEGER,
46            nombre TEXT,
47            FOREIGN KEY (rol_id) REFERENCES roles(id)
48        )
49    ''')
50    
51    # Migraciones seguras para usuarios (NUEVO: empleado_id, activo, fecha_creacion)
52    for col, ctype in [('empleado_id', 'INTEGER'), ('activo', 'INTEGER DEFAULT 1'), ('fecha_creacion', 'TEXT')]:
53        try: c.execute(f"ALTER TABLE usuarios ADD COLUMN {col} {ctype}")
54        except: pass
55    
56    # Proyectos y módulos básicos
57    c.execute('''
58        CREATE TABLE IF NOT EXISTS proyectos (
59            id INTEGER PRIMARY KEY AUTOINCREMENT,
60            nombre TEXT,
61            descripcion TEXT,
62            estado TEXT,
63            avance INTEGER DEFAULT 0,
64            fecha_inicio TEXT,
65            fecha_fin TEXT,
66            cliente_id INTEGER,
67            cliente_nombre TEXT,
68            tipo_proyecto TEXT,
69            ubicacion TEXT,
70            
71            -- Responsables Detallados
72            director_id INTEGER,
73            residente_id INTEGER,
74            supervisor_id INTEGER,
75            sst_id INTEGER,
76            logistica_id INTEGER,
77            
78            FOREIGN KEY (director_id) REFERENCES usuarios(id),
79            FOREIGN KEY (residente_id) REFERENCES usuarios(id),
80            FOREIGN KEY (supervisor_id) REFERENCES usuarios(id),
81            FOREIGN KEY (sst_id) REFERENCES usuarios(id),
82            FOREIGN KEY (logistica_id) REFERENCES usuarios(id),
83            FOREIGN KEY (cliente_id) REFERENCES usuarios(id)
84        )
85    ''')
86    
87    # CRM y Relaciones Corporativas
88    c.execute('''
89        CREATE TABLE IF NOT EXISTS crm_clientes (
90            id INTEGER PRIMARY KEY AUTOINCREMENT,
91            nit TEXT,
92            nombre TEXT NOT NULL,
93            tipo TEXT,
94            industria TEXT,
95            contacto_principal TEXT,
96            telefono TEXT,
97            email TEXT,
98            direccion TEXT,
99            ciudad TEXT,
100            estado TEXT DEFAULT 'Activo',
101            notas TEXT,
102            fecha_creacion TEXT
103        )
104    ''')
105    
106    c.execute('''
107        CREATE TABLE IF NOT EXISTS crm_oportunidades (
108            id INTEGER PRIMARY KEY AUTOINCREMENT,
109            cliente_id INTEGER,
110            titulo TEXT NOT NULL,
111            valor REAL DEFAULT 0,
112            etapa TEXT DEFAULT 'Prospección',
113            fecha_cierre TEXT,
114            probabilidad INTEGER DEFAULT 50,
115            responsable_id INTEGER,
116            notas TEXT,
117            fecha_creacion TEXT,
118            FOREIGN KEY (cliente_id) REFERENCES crm_clientes(id),
119            FOREIGN KEY (responsable_id) REFERENCES usuarios(id)
120        )
121    ''')
122    
123    # Migraciones seguras para columnas faltantes en proyectos
124    for col, col_type in [
125        ('descripcion', 'TEXT'),
126        ('fecha_fin', 'TEXT'),
127        ('cliente_id', 'INTEGER'),
128        ('cliente_nombre', 'TEXT'),
129        ('tipo_proyecto', 'TEXT'),
130        ('ubicacion', 'TEXT'),
131        ('director_id', 'INTEGER'),
132        ('residente_id', 'INTEGER'),
133        ('supervisor_id', 'INTEGER'),
134        ('sst_id', 'INTEGER'),
135        ('logistica_id', 'INTEGER'),
136        ('token_cliente', 'TEXT')
137    ]:
138        try:
139            c.execute(f"ALTER TABLE proyectos ADD COLUMN {col} {col_type}")
140        except:
141            pass
142    
143    # SST
144    c.execute('''
145        CREATE TABLE IF NOT EXISTS plantillas_formatos (
146            id INTEGER PRIMARY KEY AUTOINCREMENT,
147            nombre TEXT,
148            tipo_formato TEXT,
149            version INTEGER DEFAULT 1,
150            estructura_json TEXT,
151            activa BOOLEAN DEFAULT 1,
152            fecha_creacion TEXT,
153            creado_por TEXT
154        )
155    ''')
156    try:
157        c.execute("ALTER TABLE plantillas_formatos ADD COLUMN archivo_url TEXT")
158    except:
159        pass
160
161    c.execute('''
162        CREATE TABLE IF NOT EXISTS formatos_sst (
163            id INTEGER PRIMARY KEY AUTOINCREMENT,
164            tipo_formato TEXT,
165            id_plantilla INTEGER,
166            datos_completados_json TEXT,
167            proyecto_id INTEGER,
168            fecha TEXT,
169            creado_por TEXT,
170            archivo_url TEXT,
171            estado TEXT DEFAULT 'Pendiente',
172            FOREIGN KEY (proyecto_id) REFERENCES proyectos(id),
173            FOREIGN KEY (id_plantilla) REFERENCES plantillas_formatos(id)
174        )
175    ''')
176    
177    try:
178        c.execute("ALTER TABLE formatos_sst ADD COLUMN datos_completados_json TEXT")
179        c.execute("ALTER TABLE formatos_sst ADD COLUMN id_plantilla INTEGER")
180        c.execute("ALTER TABLE formatos_sst ADD COLUMN estado TEXT DEFAULT 'Pendiente'")
181    except:
182        pass
183
184    # --- MÓDULO SST INDUSTRIAL ELITE (SG-SST / ISO 45001) ---
185    
186    # 1. Matriz Legal Dinámica (Decreto 1072)
187    c.execute('''
188        CREATE TABLE IF NOT EXISTS sst_matriz_legal (
189            id INTEGER PRIMARY KEY AUTOINCREMENT,
190            norma TEXT, -- Ej: Decreto 1072 de 2015
191            articulo TEXT,
192            descripcion TEXT,
193            evidencia_requerida TEXT,
194            estado_cumplimiento TEXT DEFAULT 'Pendiente', -- Cumple, No Cumple, Parcial
195            fecha_verificacion TEXT,
196            version_norma TEXT DEFAULT 'Original',
197            derogada BOOLEAN DEFAULT 0
198        )
199    ''')
200
201    # 2. Matriz de Peligros (IPVR - GTC 45)
202    c.execute('''
203        CREATE TABLE IF NOT EXISTS sst_matriz_peligros (
204            id INTEGER PRIMARY KEY AUTOINCREMENT,
205            proyecto_id INTEGER,
206            proceso TEXT,
207            subproceso TEXT,
208            zona TEXT,
209            actividad TEXT,
210            tarea TEXT,
211            peligro_descripcion TEXT,
212            clasificacion TEXT, -- Físico, Químico, Biológico, Biomecánico, etc.
213            efectos_posibles TEXT,
214            personas_expuestas INTEGER DEFAULT 1,
215            nivel_deficiencia INTEGER, -- ND
216            nivel_exposicion INTEGER,   -- NE
217            nivel_probabilidad INTEGER, -- NP
218            nivel_consecuencia INTEGER, -- NC
219            nivel_riesgo_valor INTEGER, -- NR
220            interpretacion_riesgo TEXT, -- I, II, III, IV
221            controles_eliminacion TEXT,
222            controles_sustitucion TEXT,
223            controles_ingenieria TEXT,
224            controles_administrativos TEXT,
225            controles_epp TEXT,
226            controles_existentes TEXT, -- Legado
227            controles_propuestos TEXT, -- Legado
228            accion_requerida TEXT,
229            responsable TEXT,
230            estado TEXT DEFAULT 'Identificado',
231            fecha_evaluacion TEXT,
232            FOREIGN KEY (proyecto_id) REFERENCES proyectos(id)
233        )
234    ''')
235
236    # Migraciones para GTC-45 profesional
237    for col, ctype in [
238        ('subproceso', 'TEXT'),
239        ('tarea', 'TEXT'),
240        ('personas_expuestas', 'INTEGER DEFAULT 1'),
241        ('nivel_probabilidad', 'INTEGER'),
242        ('controles_eliminacion', 'TEXT'),
243        ('controles_sustitucion', 'TEXT'),
244        ('controles_ingenieria', 'TEXT'),
245        ('controles_administrativos', 'TEXT'),
246        ('controles_epp', 'TEXT'),
247        ('accion_requerida', 'TEXT'),
248        ('responsable', 'TEXT'),
249        ('estado', "TEXT DEFAULT 'Identificado'"),
250        ('nivel_riesgo_inicial', 'INTEGER'),
251        ('nivel_riesgo_residual', 'INTEGER')
252    ]:
253        try: c.execute(f"ALTER TABLE sst_matriz_peligros ADD COLUMN {col} {ctype}")
254        except: pass
255
256    # Tablas para Gestión GTC-45 Profesional
257    c.execute('''
258        CREATE TABLE IF NOT EXISTS sst_riesgo_plan_accion (
259            id INTEGER PRIMARY KEY AUTOINCREMENT,
260            riesgo_id INTEGER,
261            accion_correctiva TEXT,
262            responsable TEXT,
263            fecha_inicio TEXT,
264            fecha_limite TEXT,
265            estado TEXT DEFAULT 'Pendiente',
266            prioridad TEXT DEFAULT 'Media',
267            evidencias_json TEXT,
268            FOREIGN KEY (riesgo_id) REFERENCES sst_matriz_peligros(id)
269        )
270    ''')
271    
272    # Migración prioridad
273    try: c.execute("ALTER TABLE sst_riesgo_plan_accion ADD COLUMN prioridad TEXT DEFAULT 'Media'")
274    except: pass
275
276    c.execute('''
277        CREATE TABLE IF NOT EXISTS sst_riesgo_evidencias (
278            id INTEGER PRIMARY KEY AUTOINCREMENT,
279            riesgo_id INTEGER,
280            archivo_nombre TEXT,
281            archivo_ruta TEXT,
282            tipo_evidencia TEXT,
283            fecha_carga TEXT,
284            usuario_id INTEGER,
285            FOREIGN KEY (riesgo_id) REFERENCES sst_matriz_peligros(id)
286        )
287    ''')
288
289    c.execute('''
290        CREATE TABLE IF NOT EXISTS sst_riesgo_historial (
291            id INTEGER PRIMARY KEY AUTOINCREMENT,
292            riesgo_id INTEGER,
293            fecha_cambio TEXT,
294            usuario_id INTEGER,
295            campo_modificado TEXT,
296            valor_anterior TEXT,
297            valor_nuevo TEXT,
298            FOREIGN KEY (riesgo_id) REFERENCES sst_matriz_peligros(id)
299        )
300    ''')
301
302    # 3. Plan Anual SG-SST (PHVA - Gestión Estratégica)
303    c.execute('''
304        CREATE TABLE IF NOT EXISTS sst_plan_anual (
305            id INTEGER PRIMARY KEY AUTOINCREMENT,
306            anio INTEGER DEFAULT 2026,
307            nombre_actividad TEXT,
308            descripcion TEXT, -- NUEVO
309            tipo_actividad TEXT, -- Inspección, Capacitación, Simulacro, Auditoría, Médica, Mantenimiento
310            fase_phva TEXT, -- Planear, Hacer, Verificar, Actuar
311            area_responsable TEXT,
312            responsable_id INTEGER,
313            frecuencia TEXT, -- Mensual, Trimestral, Semestral, Anual, Única
314            presupuesto_estimado REAL DEFAULT 0.0,
315            fecha_programada TEXT,
316            hora_programada TEXT, -- NUEVO
317            duracion_estimada TEXT, -- NUEVO (ej: 2h 30m)
318            fecha_ejecucion TEXT,
319            avance_porcentaje INTEGER DEFAULT 0,
320            estado TEXT DEFAULT 'Programada', -- Programada, En ejecución, Completada, Vencida, Borrador
321            
322            -- Enfoque SST y Participantes
323            riesgo_id INTEGER, -- Link IPVR
324            tipo_capacitacion TEXT, -- Técnica, Normativa, Soft Skills, etc.
325            es_obligatoria BOOLEAN DEFAULT 1,
326            participantes_json TEXT, -- Lista de IDs de trabajadores asistentes
327            
328            -- Seguimiento y Control
329            indicador_esperado TEXT,
330            metodo_verificacion TEXT,
331            evidencia_requerida TEXT,
332            evidencia_json TEXT, -- Lista de URLs de soportes (fotos, actas, PDFs)
333            
334            FOREIGN KEY (responsable_id) REFERENCES usuarios(id),
335            FOREIGN KEY (riesgo_id) REFERENCES sst_matriz_peligros(id)
336        )
337    ''')
338    
339    # Migraciones seguras para sst_plan_anual (campos profesionales)
340    for col, ctype in [
341        ('anio', 'INTEGER DEFAULT 2026'),
342        ('descripcion', 'TEXT'),
343        ('hora_programada', 'TEXT'),
344        ('duracion_estimada', 'TEXT'),
345        ('riesgo_id', 'INTEGER'),
346        ('tipo_capacitacion', 'TEXT'),
347        ('es_obligatoria', 'BOOLEAN DEFAULT 1'),
348        ('participantes_json', 'TEXT'),
349        ('indicador_esperado', 'TEXT'),
350        ('metodo_verificacion', 'TEXT'),
351        ('evidencia_requerida', 'TEXT')
352    ]:
353        try: c.execute(f"ALTER TABLE sst_plan_anual ADD COLUMN {col} {ctype}")
354        except: pass
355
356    # 4. Gestión Médica Ocupacional (Privada)
357    c.execute('''
358        CREATE TABLE IF NOT EXISTS sst_gestion_medica (
359            id INTEGER PRIMARY KEY AUTOINCREMENT,
360            usuario_id INTEGER,
361            tipo_examen TEXT, -- Ingreso, Periódico, Egreso
362            fecha_examen TEXT,
363            concepto_aptitud TEXT, -- Apto, Apto con restricciones, No Apto
364            recomendaciones TEXT, -- Enmascarado/Restringido según LOPD
365            vencimiento_examen TEXT,
366            entidad_medica TEXT,
367            FOREIGN KEY (usuario_id) REFERENCES usuarios(id)
368        )
369    ''')
370
371    # 5. Inspecciones de Campo (Checklists Dinámicos)
372    c.execute('''
373        CREATE TABLE IF NOT EXISTS sst_inspecciones (
374            id INTEGER PRIMARY KEY AUTOINCREMENT,
375            fecha TEXT,
376            area TEXT,
377            proceso TEXT,
378            tipo_inspeccion TEXT, -- Puestos de trabajo, EPP, Alturas, Eléctrica
379            inspector_id INTEGER,
380            ubicacion TEXT,
381            nivel_riesgo_estimado TEXT,
382            estado TEXT DEFAULT 'En proceso', -- En proceso, Finalizada, Cerrada
383            
384            -- Legado / Adicionales
385            proyecto_id INTEGER,
386            entidad TEXT, -- Empresa o Contratista
387            datos_json TEXT, -- Estructura flexible para checklist respuestas
388            geolocalizacion TEXT,
389            foto_evidencia_url TEXT,
390            firma_inspector_url TEXT,
391            firma_auditado_url TEXT,
392            calificacion_final REAL DEFAULT 100.0,
393            
394            FOREIGN KEY (proyecto_id) REFERENCES proyectos(id) ON DELETE CASCADE,
395            FOREIGN KEY (inspector_id) REFERENCES usuarios(id) ON DELETE SET NULL
396        )
397    ''')
398
399    # Hallazgos de Inspección (Reporte de Hallazgos Pro)
400    c.execute('''
401        CREATE TABLE IF NOT EXISTS sst_hallazgos (
402            id INTEGER PRIMARY KEY AUTOINCREMENT,
403            inspeccion_id INTEGER,
404            tipo_hallazgo TEXT, -- Acto Inseguro, Condición Insegura, Auditoría, Reporte Externo
405            fecha_deteccion TEXT,
406            area_o_ubicacion TEXT,
407            proceso_o_actividad TEXT,
408            usuario_reporta_id INTEGER,
409            descripcion TEXT,
410            causa_probable TEXT,
411            categoria_hallazgo TEXT,
412            nivel_riesgo TEXT, -- Bajo, Medio, Alto, Crítico
413            evidencia_url TEXT,
414            documentos_adjuntos_json TEXT,
415            comentarios_json TEXT,
416            accion_correctiva_id INTEGER, -- Link a sst_plan_accion o sst_capa
417            estado TEXT DEFAULT 'Abierto', -- Abierto, En proceso, Pendiente verificación, Cerrado
418            FOREIGN KEY (inspeccion_id) REFERENCES sst_inspecciones(id),
419            FOREIGN KEY (usuario_reporta_id) REFERENCES usuarios(id),
420            FOREIGN KEY (accion_correctiva_id) REFERENCES sst_plan_accion(id)
421        )
422    ''')
423
424    # Migración segura para sst_hallazgos (campos profesionales)
425    for col, ctype in [
426        ('fecha_deteccion', 'TEXT'),
427        ('area_o_ubicacion', 'TEXT'),
428        ('proceso_o_actividad', 'TEXT'),
429        ('usuario_reporta_id', 'INTEGER'),
430        ('causa_probable', 'TEXT'),
431        ('categoria_hallazgo', 'TEXT'),
432        ('documentos_adjuntos_json', 'TEXT'),
433        ('comentarios_json', 'TEXT'),
434        ('responsable_id', 'INTEGER'),
435        ('item_id', 'INTEGER')
436    ]:
437        try: c.execute(f"ALTER TABLE sst_hallazgos ADD COLUMN {col} {ctype}")
438        except: pass
439
440    # 6. Acciónes Correctivas y Preventivas (CAPA / Planes de Acción)
441    c.execute('''
442        CREATE TABLE IF NOT EXISTS sst_capa (
443            id INTEGER PRIMARY KEY AUTOINCREMENT,
444            fuente_id INTEGER, -- ID de accidente, auditoría o inspección
445            fuente_tipo TEXT, -- 'Accidente', 'Inspección', 'Auditoría'
446            hallazgo TEXT,
447            analisis_causa TEXT,
448            accion_propuesta TEXT,
449            responsable_id INTEGER,
450            fecha_compromiso TEXT,
451            fecha_cierre TEXT,
452            estado TEXT DEFAULT 'Abierta',
453            reincidencia BOOLEAN DEFAULT 0,
454            FOREIGN KEY (responsable_id) REFERENCES usuarios(id)
455        )
456    ''')
457    
458    # Tabla para gestionar plantillas de checklists reutilizables (SST Pro)
459    c.execute('''
460        CREATE TABLE IF NOT EXISTS sst_inspeccion_plantillas (
461            id INTEGER PRIMARY KEY AUTOINCREMENT,
462            nombre TEXT,
463            descripcion TEXT,
464            categoria TEXT, -- Seguridad General, Alturas, EPP, Maquinaria, etc.
465            area TEXT,
466            nivel_riesgo TEXT,
467            fecha_creacion TEXT,
468            estado TEXT DEFAULT 'Activo'
469        )
470    ''')
471
472    c.execute('''
473        CREATE TABLE IF NOT EXISTS sst_inspeccion_items (
474            id INTEGER PRIMARY KEY AUTOINCREMENT,
475            plantilla_id INTEGER,
476            item_texto TEXT,
477            categoria_item TEXT,
478            FOREIGN KEY (plantilla_id) REFERENCES sst_inspeccion_plantillas(id)
479        )
480    ''')
481
482    c.execute('''
483        CREATE TABLE IF NOT EXISTS sst_inspeccion_respuestas (
484            id INTEGER PRIMARY KEY AUTOINCREMENT,
485            inspeccion_id INTEGER,
486            item_id INTEGER,
487            cumple BOOLEAN, -- 1 o 0
488            observaciones TEXT,
489            evidencia_ruta TEXT,
490            hallazgo_id INTEGER,
491            serial_equipo TEXT,
492            FOREIGN KEY (inspeccion_id) REFERENCES sst_inspecciones(id),
493            FOREIGN KEY (item_id) REFERENCES sst_inspeccion_items(id),
494            FOREIGN KEY (hallazgo_id) REFERENCES sst_hallazgos(id)
495        )
496    ''')
497
498    c.execute('''
499        CREATE TABLE IF NOT EXISTS sst_acciones_correctivas (
500            id INTEGER PRIMARY KEY AUTOINCREMENT,
501            accidente_id INTEGER, -- Para accidentes
502            hallazgo_id INTEGER, -- Para hallazgos de inspección
503            accion_propuesta TEXT,
504            responsable_id INTEGER,
505            fecha_compromiso TEXT,
506            fecha_creacion TEXT,
507            prioridad TEXT DEFAULT 'Media',
508            estado TEXT DEFAULT 'Pendiente',
509            FOREIGN KEY (accidente_id) REFERENCES accidentes_laborales(id),
510            FOREIGN KEY (hallazgo_id) REFERENCES sst_hallazgos(id),
511            FOREIGN KEY (responsable_id) REFERENCES usuarios(id)
512        )
513    ''')
514
515
516    # Tabla espejo o alias para compatibilidad con servicios extendidos (sst_plan_accion)
517    c.execute('''
518        CREATE TABLE IF NOT EXISTS sst_plan_accion (
519            id INTEGER PRIMARY KEY AUTOINCREMENT,
520            descripcion TEXT,
521            prioridad TEXT,
522            estado TEXT DEFAULT 'Pendiente',
523            fecha_limite TEXT,
524            responsable_id INTEGER,
525            proyecto_id INTEGER,
526            FOREIGN KEY (responsable_id) REFERENCES usuarios(id),
527            FOREIGN KEY (proyecto_id) REFERENCES proyectos(id)
528        )
529    ''')
530    for col, ctype in [('investigacion_id', 'INTEGER'), ('actividad', 'TEXT')]:
531        try: c.execute(f"ALTER TABLE sst_plan_accion ADD COLUMN {col} {ctype}")
532        except: pass
533
534    # --- MÓDULO SST CONTROL CENTER PRO (REESTRUCTURACIÓN) ---
535    
536    # 5. Pipeline y Gestión de Eventos
537    for tbl in ['accidentes_laborales', 'sst_incidentes']:
538        for col, ctype in [('etapa_flujo', 'TEXT DEFAULT "Reportado"'), ('prioridad', 'TEXT DEFAULT "Media"'), ('riesgo_score', 'INTEGER DEFAULT 0')]:
539            try: c.execute(f"ALTER TABLE {tbl} ADD COLUMN {col} {ctype}")
540            except: pass
541
542    # 6. Consola de Investigación Avanzada
543    for col, ctype in [
544        ('metodologia_5_porques', 'TEXT'), 
545        ('metodologia_ishikawa', 'TEXT'), 
546        ('arbol_causas_json', 'TEXT'), 
547        ('analisis_ia_sara', 'TEXT'),
548        ('severidad_dias_perdidos', 'INTEGER DEFAULT 0')
549    ]:
550        try: c.execute(f"ALTER TABLE sst_investigaciones ADD COLUMN {col} {ctype}")
551        except: pass
552
553    # 7. Motor de Planes de Acción Elite
554    for col, ctype in [
555        ('tipo_accion', 'TEXT DEFAULT "Correctiva"'), 
556        ('prioridad', 'TEXT DEFAULT "Media"'),
557        ('costo_estimado', 'REAL DEFAULT 0'),
558        ('avance_progreso', 'INTEGER DEFAULT 0')
559    ]:
560        try: c.execute(f"ALTER TABLE sst_plan_accion ADD COLUMN {col} {ctype}")
561        except: pass
562
563    # 8. Metadatos de Seguridad (Para KPIs Dinámicos)
564    c.execute('''
565        CREATE TABLE IF NOT EXISTS sst_indicadores_mensuales (
566            id INTEGER PRIMARY KEY AUTOINCREMENT,
567            mes_anio TEXT UNIQUE, -- Ej: 2024-03
568            horas_hombre_trabajadas INTEGER,
569            num_trabajadores INTEGER,
570            tasa_frecuencia REAL,
571            indice_severidad REAL,
572            tasa_mortalidad REAL
573        )
574    ''')
575    
576    # 9. Historial de Chat (SARA IA) - Memoria Persistente
577    c.execute('''
578        CREATE TABLE IF NOT EXISTS sst_chat_history (
579            id INTEGER PRIMARY KEY AUTOINCREMENT,
580            rol_nombre TEXT,
581            usuario_id INTEGER,
582            mensaje_usuario TEXT,
583            respuesta_ia TEXT,
584            timestamp TEXT DEFAULT CURRENT_TIMESTAMP,
585            FOREIGN KEY (usuario_id) REFERENCES usuarios(id)
586        )
587    ''')
588
589    # Investigaciones Detalladas
590    c.execute('''
591        CREATE TABLE IF NOT EXISTS sst_investigaciones (
592            id INTEGER PRIMARY KEY AUTOINCREMENT,
593            relacion_tipo TEXT, -- 'Accidente' o 'Incidente'
594            relacion_id INTEGER,
595            metodo TEXT, -- 'Arbol de Causas', '5 Porques'
596            hallazgos TEXT,
597            conclusiones TEXT,
598            investigador_id INTEGER,
599            fecha_investigacion TEXT,
600            FOREIGN KEY (investigador_id) REFERENCES usuarios(id)
601        )
602    ''')
603
604    # 7. Auditoría Inmutable (Log de Cumplimiento)
605    c.execute('''
606        CREATE TABLE IF NOT EXISTS sst_audit_trail (
607            id INTEGER PRIMARY KEY AUTOINCREMENT,
608            usuario_id INTEGER,
609            timestamp TEXT DEFAULT CURRENT_TIMESTAMP,
610            modulo TEXT,
611            accion TEXT,
612            valor_anterior TEXT,
613            valor_nuevo TEXT,
614            hash_integridad TEXT -- Firmado para inmutabilidad simulada
615        )
616    ''')
617
618    # 8. Auditoría Operativa (Usada por servicios_sst_ext)
619    c.execute('''
620        CREATE TABLE IF NOT EXISTS sst_auditoria (
621            id INTEGER PRIMARY KEY AUTOINCREMENT,
622            usuario_id INTEGER,
623            accion TEXT,
624            modulo TEXT,
625            referencia_id INTEGER,
626            detalles TEXT,
627            fecha TEXT,
628            FOREIGN KEY (usuario_id) REFERENCES usuarios(id)
629        )
630    ''')
631
632    # Tablas de Accidentes e Incidentes (Mejoradas)
633    c.execute('''
634        CREATE TABLE IF NOT EXISTS accidentes_laborales (
635            id INTEGER PRIMARY KEY AUTOINCREMENT,
636            usuario_id INTEGER,
637            proyecto_id INTEGER,
638            fecha_accidente TEXT,
639            lugar TEXT,
640            descripcion TEXT,
641            gravedad TEXT,
642            testigos TEXT,
643            fecha_reporte TEXT,
644            estado TEXT DEFAULT 'Reportado',
645            evidencia_url TEXT,
646            investigador_id INTEGER,
647            causa_raiz TEXT,
648            tipo_lesion TEXT,
649            parte_cuerpo TEXT,
650            incapacidad_dias INTEGER,
651            reporte_arl TEXT,
652            tipo_vinculacion TEXT,
653            cargo_afectado TEXT,
654            mecanismo_accidente TEXT,
655            agente_accidente TEXT,
656            jornada_suceso TEXT,
657            fecha_notificacion_arl TEXT,
658            FOREIGN KEY (usuario_id) REFERENCES usuarios(id),
659            FOREIGN KEY (proyecto_id) REFERENCES proyectos(id)
660        )
661    ''')
662    
663    # Safe fallback migration for FURAT Colombian standards
664    try:
665        c.execute("ALTER TABLE accidentes_laborales ADD COLUMN tipo_vinculacion TEXT")
666        c.execute("ALTER TABLE accidentes_laborales ADD COLUMN cargo_afectado TEXT")
667        c.execute("ALTER TABLE accidentes_laborales ADD COLUMN mecanismo_accidente TEXT")
668        c.execute("ALTER TABLE accidentes_laborales ADD COLUMN agente_accidente TEXT")
669        c.execute("ALTER TABLE accidentes_laborales ADD COLUMN jornada_suceso TEXT")
670        c.execute("ALTER TABLE accidentes_laborales ADD COLUMN fecha_notificacion_arl TEXT")
671    except:
672        pass
673
674    c.execute('''
675        CREATE TABLE IF NOT EXISTS sst_incidentes (
676            id INTEGER PRIMARY KEY AUTOINCREMENT,
677            usuario_id INTEGER,
678            proyecto_id INTEGER,
679            fecha_incidente TEXT,
680            lugar TEXT,
681            descripcion TEXT,
682            fecha_reporte TEXT,
683            estado TEXT DEFAULT 'Reportado',
684            FOREIGN KEY (usuario_id) REFERENCES usuarios(id)
685        )
686    ''')
687
688    c.execute('''
689        CREATE TABLE IF NOT EXISTS sst_permisos_trabajo (
690            id INTEGER PRIMARY KEY AUTOINCREMENT,
691            proyecto_id INTEGER,
692            solicitante_id INTEGER,
693            supervisor_id INTEGER,
694            estado TEXT DEFAULT 'Borrador', -- Borrador, Pendiente, Aprobado, Cerrado, Cancelado
695            tipo_trabajo TEXT, -- Alturas, Caliente, Eléctrico, Espacio Confinado, Izaje, etc.
696            fecha_emision TEXT,
697            fecha_vencimiento TEXT,
698            descripcion_tarea TEXT,
699            riesgos_json TEXT, -- Almacena lista de riesgos dinámicos
700            medidas_json TEXT, -- Almacena medidas de control
701            geolocalizacion TEXT,
702            firma_autorizado TEXT,
703            tenant_id TEXT DEFAULT 'default', -- Preparado para SaaS Enterprise
704            FOREIGN KEY (proyecto_id) REFERENCES proyectos(id),
705            FOREIGN KEY (solicitante_id) REFERENCES usuarios(id),
706            FOREIGN KEY (supervisor_id) REFERENCES usuarios(id)
707        )
708    ''')
709
710    # Migraciones para Permisos de Trabajo Pro
711    for col, ctype in [
712        ('fecha_creacion', 'TEXT'),
713        ('description', 'TEXT'),
714        ('vigencia', 'TEXT'),
715        ('personal_operativo_json', 'TEXT'),
716        ('controles_verificados_json', 'TEXT'),
717        ('aro_id', 'INTEGER'),
718        ('jsa_id', 'INTEGER'),
719        ('avalado_por_she_id', 'INTEGER'),
720        ('fecha_aval_she', 'TEXT'),
721        ('comentarios_she', 'TEXT'),
722        ('usuario_id', 'INTEGER')
723    ]:
724        try: c.execute(f"ALTER TABLE sst_permisos_trabajo ADD COLUMN {col} {ctype}")
725        except: pass
726
727    c.execute('''
728        CREATE TABLE IF NOT EXISTS sst_solicitudes_permisos (
729            id INTEGER PRIMARY KEY AUTOINCREMENT,
730            proyecto_id INTEGER,
731            solicitante_id INTEGER,
732            responsable_sst_id INTEGER,
733            fecha_solicitud TEXT,
734            estado TEXT DEFAULT 'Pendiente',
735            detalles TEXT,
736            comentarios TEXT,
737            consecutivo TEXT,
738            actividad_id INTEGER,
739            FOREIGN KEY (proyecto_id) REFERENCES proyectos(id)
740        )
741    ''')
742
743    # Migración segura para solicitudes
744    for col, ctype in [
745        ('consecutivo', 'TEXT'),
746        ('actividad_id', 'INTEGER'),
747        ('solicitante_id', 'INTEGER'),
748        ('fecha_solicitud', 'TEXT')
749    ]:
750        try: c.execute(f"ALTER TABLE sst_solicitudes_permisos ADD COLUMN {col} {ctype}")
751        except: pass
752    
753    # --- MÓDULO DE GESTIÓN DE PERSONAL PRO ---
754    c.execute('''
755        CREATE TABLE IF NOT EXISTS empleados (
756            id INTEGER PRIMARY KEY AUTOINCREMENT,
757            nombre TEXT NOT NULL,
758            tipo_documento TEXT DEFAULT 'Cédula de Ciudadanía',
759            documento TEXT NOT NULL UNIQUE,
760            cargo TEXT,
761            area TEXT,
762            telefono TEXT,
763            correo TEXT,
764            fecha_ingreso TEXT,
765            estado TEXT DEFAULT 'Activo',
766            tipo_contrato TEXT,
767            hoja_vida TEXT,
768            eps TEXT,
769            arl TEXT,
770            fondo_pension TEXT,
771            nivel_riesgo TEXT,
772            ciudad TEXT,
773            centro_trabajo TEXT,
774            proyecto_id INTEGER,
775            FOREIGN KEY (proyecto_id) REFERENCES proyectos(id)
776        )
777    ''')
778    
779    for col, ctype in [
780        ('tipo_documento', 'TEXT DEFAULT "Cédula de Ciudadanía"'),
781        ('eps', 'TEXT'), ('arl', 'TEXT'), ('fondo_pension', 'TEXT'),
782        ('nivel_riesgo', 'TEXT'), ('ciudad', 'TEXT'), ('centro_trabajo', 'TEXT'),
783        ('proyecto_id', 'INTEGER'), ('firma_url', 'TEXT')
784    ]:
785        try: c.execute(f"ALTER TABLE empleados ADD COLUMN {col} {ctype}")
786        except: pass
787    
788    c.execute('''
789        CREATE TABLE IF NOT EXISTS sst_cursos (
790            id INTEGER PRIMARY KEY AUTOINCREMENT,
791            nombre TEXT NOT NULL,
792            proyecto_id INTEGER,
793            fecha_sesion TEXT,
794            temas_tratados TEXT,
795            descripcion TEXT,
796            duracion TEXT, -- Ej: 40h
797            tipo TEXT, -- Inducción, Reinducción, SST Obligatorio, Técnico
798            periodicidad_reinduccion INTEGER DEFAULT 12, -- Meses para reinducción
799            obligatorio BOOLEAN DEFAULT 1,
800            entidad TEXT, -- SENA, ARL, o Empresa Propia
801            instructor_interno BOOLEAN DEFAULT 0,
802            personal_json TEXT, -- Lista de IDs de trabajadores asistentes
803            observaciones TEXT,
804            estado TEXT DEFAULT 'Activo',
805            fecha_registro TEXT,
806            FOREIGN KEY (proyecto_id) REFERENCES proyectos(id)
807        )
808    ''')
809    
810    # Migración segura para campos nuevos
811    for col, ctype in [('proyecto_id', 'INTEGER'), ('fecha_sesion', 'TEXT'), ('temas_tratados', 'TEXT'), ('observaciones', 'TEXT')]:
812        try: c.execute(f"ALTER TABLE sst_cursos ADD COLUMN {col} {ctype}")
813        except: pass
814
815    c.execute('''
816        CREATE TABLE IF NOT EXISTS sst_certificaciones (
817            id INTEGER PRIMARY KEY AUTOINCREMENT,
818            usuario_id INTEGER,
819            tipo TEXT,
820            fecha_emision TEXT,
821            fecha_vencimiento TEXT,
822            entidad TEXT,
823            archivo_url TEXT,
824            estado TEXT DEFAULT 'Vigente',
825            FOREIGN KEY (usuario_id) REFERENCES usuarios(id)
826        )
827    ''')
828
829    c.execute('''
830        CREATE TABLE IF NOT EXISTS activos_certificaciones (
831            id INTEGER PRIMARY KEY AUTOINCREMENT,
832            activo_id INTEGER,
833            tipo TEXT,
834            fecha_emision TEXT,
835            fecha_vencimiento TEXT,
836            entidad TEXT,
837            archivo_url TEXT,
838            estado TEXT DEFAULT 'Vigente'
839        )
840    ''')
841
842    c.execute('''
843        CREATE TABLE IF NOT EXISTS inventario_herramientas (
844            id INTEGER PRIMARY KEY AUTOINCREMENT,
845            nombre TEXT,
846            marca TEXT,
847            modelo TEXT,
848            serial TEXT,
849            estado TEXT DEFAULT 'Disponible',
850            responsable TEXT,
851            ubicacion TEXT,
852            fecha_compra TEXT,
853            garantia TEXT,
854            asignado_a_proyecto INTEGER,
855            FOREIGN KEY (asignado_a_proyecto) REFERENCES proyectos(id)
856        )
857    ''')
858    
859    # Migraciones para inventario_herramientas
860    for col, ctype in [
861        ('marca', 'TEXT'), ('modelo', 'TEXT'), ('serial', 'TEXT'), 
862        ('responsable', 'TEXT'), ('ubicacion', 'TEXT'), 
863        ('fecha_compra', 'TEXT'), ('garantia', 'TEXT'),
864        ('categoria_id', 'INTEGER'), ('foto_url', 'TEXT')
865    ]:
866        try: c.execute(f"ALTER TABLE inventario_herramientas ADD COLUMN {col} {ctype}")
867        except: pass
868    
869    c.execute('''
870        CREATE TABLE IF NOT EXISTS inventario_materiales (
871            id INTEGER PRIMARY KEY AUTOINCREMENT,
872            nombre TEXT,
873            cantidad REAL,
874            unidad TEXT
875        )
876    ''')
877    
878    c.execute('''
879        CREATE TABLE IF NOT EXISTS actividades_proyecto (
880            id INTEGER PRIMARY KEY AUTOINCREMENT,
881            proyecto_id INTEGER,
882            nombre TEXT,
883            descripcion TEXT,
884            tipo_actividad TEXT,
885            prioridad TEXT DEFAULT 'Media', -- Baja, Media, Alta, Crítica
886            duracion_estimada TEXT,
887            requiere_aro BOOLEAN DEFAULT 0,
888            requiere_jsa BOOLEAN DEFAULT 0,
889            requiere_permiso BOOLEAN DEFAULT 0,
890            fecha_inicio TEXT,
891            fecha_fin TEXT,
892            estado TEXT DEFAULT 'Pendiente', -- Pendiente, En proceso, Completada, Retrasada
893            responsable_id INTEGER,
894            responsable_sst_id INTEGER,
895            personal_operativo_json TEXT, 
896            tipos_permiso_json TEXT,
897            hora_inicio TEXT,
898            hora_fin TEXT,
899            evidencias_json TEXT,
900            documentos_legales_json TEXT,
901            FOREIGN KEY (proyecto_id) REFERENCES proyectos(id),
902            FOREIGN KEY (responsable_id) REFERENCES usuarios(id),
903            FOREIGN KEY (responsable_sst_id) REFERENCES usuarios(id)
904        )
905    ''')
906    
907    for col, col_type in [
908        ('nombre', 'TEXT'),
909        ('descripcion', 'TEXT'),
910        ('prioridad', "TEXT DEFAULT 'Media'"), 
911        ('duracion_estimada', 'TEXT'), 
912        ('tipo_actividad', 'TEXT'),
913        ('fecha_inicio', 'TEXT'),
914        ('fecha_fin', 'TEXT'),
915        ('estado', "TEXT DEFAULT 'Pendiente'"),
916        ('requiere_aro', 'BOOLEAN DEFAULT 0'),
917        ('requiere_jsa', 'BOOLEAN DEFAULT 0'),
918        ('requiere_permiso', 'BOOLEAN DEFAULT 0'),
919        ('responsable_sst_id', 'INTEGER'),
920        ('personal_operativo_json', 'TEXT'),
921        ('tipos_permiso_json', 'TEXT'),
922        ('hora_inicio', 'TEXT'),
923        ('hora_fin', 'TEXT')
924    ]:
925        try: c.execute(f"ALTER TABLE actividades_proyecto ADD COLUMN {col} {col_type}")
926        except: pass
927    
928    c.execute('''
929        CREATE TABLE IF NOT EXISTS equipos_externos (
930            id INTEGER PRIMARY KEY AUTOINCREMENT,
931            nombre TEXT NOT NULL,
932            empresa_propietaria TEXT,
933            tipo TEXT,
934            contratista TEXT,
935            numero_contrato TEXT,
936            fecha_inicio TEXT,
937            fecha_fin TEXT,
938            valor REAL DEFAULT 0.0,
939            estado TEXT DEFAULT 'Disponible',
940            proyecto_actual_id INTEGER,
941            responsable_actual TEXT,
942            fecha_ingreso TEXT,
943            FOREIGN KEY (proyecto_actual_id) REFERENCES proyectos(id)
944        )
945    ''')
946    
947    c.execute('''
948        CREATE TABLE IF NOT EXISTS movimientos_externos (
949            id INTEGER PRIMARY KEY AUTOINCREMENT,
950            equipo_id INTEGER,
951            tipo_movimiento TEXT,
952            proyecto_id INTEGER,
953            usuario_id INTEGER,
954            responsable TEXT,
955            estado_equipo TEXT,
956            notas TEXT,
957            tiene_dano BOOLEAN DEFAULT 0,
958            fecha_movimiento TEXT,
959            firma_datos TEXT,
960            FOREIGN KEY (equipo_id) REFERENCES equipos_externos(id),
961            FOREIGN KEY (proyecto_id) REFERENCES proyectos(id),
962            FOREIGN KEY (usuario_id) REFERENCES usuarios(id)
963        )
964    ''')
965
966    # Seguimiento de Obras y Bitácora
967    c.execute('''
968        CREATE TABLE IF NOT EXISTS seguimiento_obras (
969            id INTEGER PRIMARY KEY AUTOINCREMENT,
970            usuario_id INTEGER,
971            proyecto_id INTEGER,
972            actividad_id INTEGER,
973            fecha TEXT,
974            actividades TEXT,
975            avance_registrado INTEGER,
976            imagen_url TEXT,
977            estado TEXT DEFAULT 'Pendiente', -- Pendiente, Aprobado, Rechazado
978            FOREIGN KEY (usuario_id) REFERENCES usuarios(id),
979            FOREIGN KEY (proyecto_id) REFERENCES proyectos(id),
980            FOREIGN KEY (actividad_id) REFERENCES actividades_proyecto(id)
981        )
982    ''')
983
984    try: c.execute("ALTER TABLE seguimiento_obras ADD COLUMN estado TEXT DEFAULT 'Pendiente'")
985    except: pass
986    try: c.execute("ALTER TABLE seguimiento_obras ADD COLUMN actividad_id INTEGER")
987    except: pass
988    try: c.execute("ALTER TABLE actividades_proyecto ADD COLUMN avance_porcentaje INTEGER DEFAULT 0")
989    except: pass
990
991    c.execute('''
992        CREATE TABLE IF NOT EXISTS inv_consumo_seguimiento (
993            id INTEGER PRIMARY KEY AUTOINCREMENT,
994            seguimiento_id INTEGER,
995            material_id INTEGER,
996            cantidad REAL,
997            FOREIGN KEY (seguimiento_id) REFERENCES seguimiento_obras(id),
998            FOREIGN KEY (material_id) REFERENCES inv_materiales_pro(id)
999        )
1000    ''')
1001
1002    c.execute('''
1003        CREATE TABLE IF NOT EXISTS novedades_ejecucion (
1004            id INTEGER PRIMARY KEY AUTOINCREMENT,
1005            usuario_id INTEGER,
1006            proyecto_id INTEGER,
1007            tipo TEXT,
1008            descripcion TEXT,
1009            fecha TEXT,
1010            impacto_dias INTEGER,
1011            estado TEXT DEFAULT 'Pendiente',
1012            evidencia_url TEXT,
1013            respuesta_gestion TEXT,
1014            gestionado_por_id INTEGER,
1015            fecha_gestion TEXT,
1016            FOREIGN KEY (usuario_id) REFERENCES usuarios(id),
1017            FOREIGN KEY (proyecto_id) REFERENCES proyectos(id),
1018            FOREIGN KEY (gestionado_por_id) REFERENCES usuarios(id)
1019        )
1020    ''')
1021
1022    c.execute('''
1023        CREATE TABLE IF NOT EXISTS material_requests (
1024            id INTEGER PRIMARY KEY AUTOINCREMENT,
1025            usuario_id INTEGER,
1026            proyecto_id INTEGER,
1027            prioridad TEXT,
1028            items_json TEXT,
1029            observaciones TEXT,
1030            estado TEXT DEFAULT 'Pendiente',
1031            respuesta_gestion TEXT,
1032            fecha_solicitud TEXT,
1033            FOREIGN KEY (usuario_id) REFERENCES usuarios(id),
1034            FOREIGN KEY (proyecto_id) REFERENCES proyectos(id)
1035        )
1036    ''')
1037    try: c.execute("ALTER TABLE material_requests ADD COLUMN estado TEXT DEFAULT 'Pendiente'")
1038    except: pass
1039    try: c.execute("ALTER TABLE material_requests ADD COLUMN respuesta_gestion TEXT")
1040    except: pass
1041
1042    c.execute('''
1043        CREATE TABLE IF NOT EXISTS proyectos_personal (
1044            id INTEGER PRIMARY KEY AUTOINCREMENT,
1045            proyecto_id INTEGER,
1046            usuario_id INTEGER,
1047            rol_en_proyecto TEXT,
1048            fecha_asignacion TEXT,
1049            FOREIGN KEY (proyecto_id) REFERENCES proyectos(id),
1050            FOREIGN KEY (usuario_id) REFERENCES usuarios(id)
1051        )
1052    ''')
1053    c.execute('''
1054        CREATE TABLE IF NOT EXISTS proyectos_bitacora (
1055            id INTEGER PRIMARY KEY AUTOINCREMENT,
1056            proyecto_id INTEGER,
1057            usuario_id INTEGER,
1058            fecha TEXT,
1059            actividades_realizadas TEXT,
1060            personal_json TEXT,
1061            materiales_json TEXT,
1062            herramientas_json TEXT,
1063            clima TEXT,
1064            incidentes TEXT,
1065            fotos_json TEXT,
1066            FOREIGN KEY (proyecto_id) REFERENCES proyectos(id),
1067            FOREIGN KEY (usuario_id) REFERENCES usuarios(id)
1068        )
1069    ''')
1070
1071    c.execute('''
1072        CREATE TABLE IF NOT EXISTS proyectos_documentos (
1073            id INTEGER PRIMARY KEY AUTOINCREMENT,
1074            proyecto_id INTEGER,
1075            nombre TEXT,
1076            tipo TEXT, -- Plano, Contrato, Informe, Otro
1077            url TEXT,
1078            usuario_id INTEGER,
1079            fecha_subida TEXT,
1080            FOREIGN KEY (proyecto_id) REFERENCES proyectos(id),
1081            FOREIGN KEY (usuario_id) REFERENCES usuarios(id)
1082        )
1083    ''')
1084    
1085    # 1. Configuración de Inventario (Submenú 1)
1086    c.execute('''
1087        CREATE TABLE IF NOT EXISTS inv_categorias (
1088            id INTEGER PRIMARY KEY AUTOINCREMENT,
1089            nombre TEXT UNIQUE,
1090            descripcion TEXT,
1091            tipo_control TEXT DEFAULT 'Stock' -- Stock, Serial, Lote
1092        )
1093    ''')
1094    
1095    c.execute('''
1096        CREATE TABLE IF NOT EXISTS inv_unidades (
1097            id INTEGER PRIMARY KEY AUTOINCREMENT,
1098            nombre TEXT UNIQUE, -- Unidad, Metro, Global, Kg, etc.
1099            abreviatura TEXT
1100        )
1101    ''')
1102
1103    # 2. Movimientos de Inventario (Kardex) (Submenú 5)
1104    c.execute('''
1105        CREATE TABLE IF NOT EXISTS inv_movimientos (
1106            id INTEGER PRIMARY KEY AUTOINCREMENT,
1107            item_id INTEGER,
1108            item_tipo TEXT, -- 'Herramienta', 'Material', 'Equipo_Externo'
1109            tipo_movimiento TEXT, -- 'Entrada', 'Salida', 'Ajuste', 'Transferencia'
1110            cantidad REAL,
1111            origen TEXT, -- Bodega, Proyecto ID, Proveedor
1112            destino TEXT, -- Bodega, Proyecto ID, Cliente
1113            referencia_factura TEXT,
1114            usuario_id INTEGER,
1115            fecha TEXT,
1116            notas TEXT,
1117            FOREIGN KEY (usuario_id) REFERENCES usuarios(id)
1118        )
1119    ''')
1120
1121    # 3. Hoja de Vida de Activos (Historial Profesional)
1122    c.execute('''
1123        CREATE TABLE IF NOT EXISTS inv_hoja_vida (
1124            id INTEGER PRIMARY KEY AUTOINCREMENT,
1125            item_id INTEGER,
1126            item_tipo TEXT, -- 'Herramienta', 'Material', 'Equipo_Externo'
1127            fecha TEXT,
1128            evento TEXT, -- Mantenimiento, Inspección, Traslado, Asignación, Incidente, Reparación
1129            descripcion TEXT,
1130            icon TEXT DEFAULT 'event',
1131            color TEXT DEFAULT 'blue',
1132            usuario_id INTEGER,
1133            FOREIGN KEY (usuario_id) REFERENCES usuarios(id)
1134        )
1135    ''')
1136
1137    # 3. Órdenes de Trabajo (Conexión Operativa)
1138    c.execute('''
1139        CREATE TABLE IF NOT EXISTS inv_ordenes_trabajo (
1140            id INTEGER PRIMARY KEY AUTOINCREMENT,
1141            codigo_ot TEXT UNIQUE,
1142            proyecto_id INTEGER,
1143            tecnico_id INTEGER,
1144            estado TEXT DEFAULT 'Abierta', -- Abierta, Ejecución, Cerrada, Cancelada
1145            fecha_apertura TEXT,
1146            fecha_cierre TEXT,
1147            descripcion_trabajo TEXT,
1148            FOREIGN KEY (proyecto_id) REFERENCES proyectos(id),
1149            FOREIGN KEY (tecnico_id) REFERENCES usuarios(id)
1150        )
1151    ''')
1152
1153    # 4. Asignación de Recursos a OT (Submenú 6)
1154    c.execute('''
1155        CREATE TABLE IF NOT EXISTS inv_asignaciones_ot (
1156            id INTEGER PRIMARY KEY AUTOINCREMENT,
1157            ot_id INTEGER,
1158            item_id INTEGER,
1159            item_tipo TEXT,
1160            cantidad_solicitada REAL,
1161            cantidad_usada REAL DEFAULT 0,
1162            cantidad_devuelta REAL DEFAULT 0,
1163            fecha_asignacion TEXT,
1164            estado TEXT DEFAULT 'Entregado', -- Entregado, Consumido, Devuelto
1165            FOREIGN KEY (ot_id) REFERENCES inv_ordenes_trabajo(id)
1166        )
1167    ''')
1168
1169    # 5. Tipos de Material y Ubicaciones (Submenú 4 y 7)
1170    c.execute('''
1171        CREATE TABLE IF NOT EXISTS inv_tipos_material (
1172            id INTEGER PRIMARY KEY AUTOINCREMENT,
1173            nombre TEXT UNIQUE,
1174            estado TEXT DEFAULT 'Activo'
1175        )
1176    ''')
1177
1178    c.execute('''
1179        CREATE TABLE IF NOT EXISTS inv_ubicaciones (
1180            id INTEGER PRIMARY KEY AUTOINCREMENT,
1181            nombre TEXT UNIQUE,
1182            tipo TEXT, -- Bodega Principal, Vehículo Técnico, Almacén Obra
1183            responsable TEXT,
1184            descripcion TEXT
1185        )
1186    ''')
1187
1188    # 6. Catálogo de Materiales Pro
1189    c.execute('''
1190        CREATE TABLE IF NOT EXISTS inv_materiales_pro (
1191            id INTEGER PRIMARY KEY AUTOINCREMENT,
1192            codigo TEXT UNIQUE,
1193            nombre TEXT,
1194            tipo_id INTEGER,
1195            categoria_id INTEGER,
1196            unidad_id INTEGER,
1197            stock_actual REAL DEFAULT 0,
1198            stock_minimo REAL DEFAULT 0,
1199            ubicacion_id INTEGER,
1200            estado TEXT DEFAULT 'Activo',

Showing the first 1,200 of 1307 lines. Download the file for the rest.