diff --git a/src/presentation/migrations/0011_load_missing_tutorials.py b/src/presentation/migrations/0011_load_missing_tutorials.py new file mode 100644 index 000000000..ee4d78bf9 --- /dev/null +++ b/src/presentation/migrations/0011_load_missing_tutorials.py @@ -0,0 +1,400 @@ +from django.db import migrations + + +TUTORIALS = [ + # Gap 2: Gestión de Usuarios en el Laboratorio + # (complemento de order 30 que cubre el QR; aquí se cubren estado, código, + # modificación y desactivación de usuarios — cap. 6 del manual) + { + 'title': 'Gestión de Usuarios en el Laboratorio', + 'slug': 'usuarios-laboratorio-gestion', + 'description': 'Estado, código de identificación, modificación y desactivación de usuarios del laboratorio', + 'url_name': 'laboratory:list_register_user_qr', + 'chapter': 'LABORATORIOS', + 'auto_start': False, + 'order': 41, + 'roles': [11, 1, 6, 10], + 'steps': [ + { + 'order': 1, 'step_key': 'usrlab-estado', 'step_type': 'MODAL', + 'title': 'Estado del usuario', + 'content': 'Cada usuario del laboratorio puede estar Activo o Inactivo. Solo los usuarios activos pueden ingresar y operar en el sistema. El estado se configura al momento del registro y puede modificarse en cualquier momento desde la gestión del usuario.', + }, + { + 'order': 2, 'step_key': 'usrlab-codigo', 'step_type': 'MODAL', + 'title': 'Código / Identificador único', + 'content': 'El sistema solicita un código único por usuario que puede corresponder al número de identificación institucional, un código interno o un código de acceso. Este código se utiliza para generar el QR personal del usuario y para identificarlo en listas de control y reportes del laboratorio.', + }, + { + 'order': 3, 'step_key': 'usrlab-qr', 'step_type': 'MODAL', + 'title': 'Código QR personal del usuario', + 'content': 'El QR generado para cada usuario sirve para: registro de ingreso al laboratorio, consulta de permisos asignados, validación de identidad y acceso a módulos autorizados. El QR puede imprimirse o mostrarse desde el dispositivo móvil.', + }, + { + 'order': 4, 'step_key': 'usrlab-modificar', 'step_type': 'MODAL', + 'title': 'Modificar datos del usuario', + 'content': 'Desde la lista de usuarios registrados puede editar: estado (activo/inactivo), rol asignado, organización de pertenencia, código de identificación y permisos asociados. Los cambios aplican de inmediato al guardar.', + }, + { + 'order': 5, 'step_key': 'usrlab-desactivar', 'step_type': 'MODAL', + 'title': 'Desactivar un usuario', + 'content': 'Cuando un usuario ya no requiere acceso al laboratorio, cambie su estado a Inactivo en lugar de eliminarlo. Esto preserva el historial completo de sus acciones (trazabilidad) y cumple con requisitos de auditoría. El usuario desactivado no puede iniciar sesión ni operar en el sistema.', + }, + ], + }, + + # Gap 3: Estadísticas de Reactivos + { + 'title': 'Estadísticas de Reactivos', + 'slug': 'estadisticas-reactivos', + 'description': 'Consultar estadísticas de consumo e inventario de reactivos por período', + 'url_name': 'laboratory:shel_objects_reactives', + 'chapter': 'LABORATORIOS', + 'auto_start': False, + 'order': 42, + 'roles': [1, 6, 10, 5, 15, 13, 14], + 'steps': [ + { + 'order': 1, 'step_key': 'stat-concepto', 'step_type': 'MODAL', + 'title': '¿Qué son las Estadísticas de Reactivos?', + 'content': 'El módulo de Estadísticas de Reactivos permite consultar métricas del inventario durante un período determinado. Es especialmente útil para cierres anuales, auditorías internas, análisis de consumo y toma de decisiones sobre reordenamiento y presupuesto.', + }, + { + 'order': 2, 'step_key': 'stat-periodo', 'step_type': 'MODAL', + 'title': 'Seleccionar período de análisis', + 'content': 'Defina el rango de fechas sobre el cual desea analizar el comportamiento del inventario. Puede consultar períodos mensuales, trimestrales o anuales. El sistema filtrará todos los movimientos de reactivos comprendidos en ese rango para generar las estadísticas.', + }, + { + 'order': 3, 'step_key': 'stat-consumo', 'step_type': 'MODAL', + 'title': 'Análisis de consumo', + 'content': 'Las estadísticas muestran cuánto se ha consumido de cada reactivo en el período seleccionado. Con esta información puede identificar los reactivos de mayor rotación, ajustar los límites de reorden y optimizar las compras para evitar desabastecimiento o acumulación innecesaria.', + }, + { + 'order': 4, 'step_key': 'stat-cierre', 'step_type': 'MODAL', + 'title': 'Cierre anual de inventario', + 'content': 'Al cierre de año, use este módulo para obtener un reporte de inventario inicial vs. final. Esto permite comparar el stock al inicio del período contra el stock actual, identificar diferencias y generar evidencia para auditorías. Los datos pueden exportarse para incluirse en informes institucionales.', + }, + ], + }, + + # Gap 4: Reportes Específicos del Laboratorio + { + 'title': 'Reportes Específicos del Laboratorio', + 'slug': 'reportes-especificos', + 'description': 'Guía detallada de cada tipo de reporte disponible y sus campos requeridos', + 'url_name': 'laboratory:reports', + 'chapter': 'GENERAL', + 'auto_start': False, + 'order': 43, + 'roles': [11, 1, 7, 6, 10, 5], + 'steps': [ + { + 'order': 1, 'step_key': 'rptdet-infregencial', 'step_type': 'MODAL', + 'title': 'Informe regencial', + 'content': 'El Informe regencial es utilizado por el regente del laboratorio. Genera un resumen en formato XLS u ODS con la información del inventario bajo su responsabilidad. Campos requeridos: elemento (laboratorio u organización) y período de consulta.', + }, + { + 'order': 2, 'step_key': 'rptdet-saludlaboral', 'step_type': 'MODAL', + 'title': 'Reporte de salud laboral', + 'content': 'Genera reportes asociados al personal del laboratorio. Se selecciona el usuario o registro deseado y el sistema descarga automáticamente el informe. Es útil para auditorías de salud ocupacional y seguimiento del personal expuesto a sustancias peligrosas.', + }, + { + 'order': 3, 'step_key': 'rptdet-muebles', 'step_type': 'MODAL', + 'title': 'Reporte de muebles y objetos en límite', + 'content': 'El Reporte de muebles genera información sobre muebles y su contenido por sala. El Reporte de objetos en límite muestra reactivos u objetos cercanos al límite mínimo o máximo configurado. Ambos requieren: laboratorio y sala como filtros principales.', + }, + { + 'order': 4, 'step_key': 'rptdet-movimientos', 'step_type': 'MODAL', + 'title': 'Reporte de movimientos y precursores', + 'content': 'El Reporte de movimientos de objetos consulta todas las entradas, salidas y transferencias de reactivos en un período. El Reporte de precursores y Objetos reactivos precursores generan el listado de sustancias con control regulatorio especial. Campos: laboratorio, período e indicador de precursor.', + }, + { + 'order': 5, 'step_key': 'rptdet-desechos', 'step_type': 'MODAL', + 'title': 'Reporte de desechos y reactivos', + 'content': 'El Reporte de desechos descarga información sobre sustancias u objetos desechados en un período. El Reporte de reactivos genera el inventario general de reactivos del laboratorio. El Reporte general por laboratorio consolida todo: inventario, movimientos, usuarios, reactivos, materiales, equipos y estado general.', + }, + { + 'order': 6, 'step_key': 'rptdet-sga', 'step_type': 'MODAL', + 'title': 'Reportes SGA y compatibilidad', + 'content': 'El Reporte de compatibilidad SGA y el Informe de laboratorio por compatibilidad generan información sobre la compatibilidad de almacenamiento según el Sistema Globalmente Armonizado. El Reporte de zonas de riesgo requiere laboratorio, zona de riesgo y edificio como filtros. El Informe de donaciones lista los objetos o sustancias ingresados por donación.', + }, + ], + }, + + # Gap 5: Tipos de Zona de Riesgo + { + 'title': 'Tipos de Zona de Riesgo', + 'slug': 'tipos-zona-riesgo', + 'description': 'Clasificación y gestión de los tipos de zona de riesgo del laboratorio', + 'url_name': 'riskmanagement:riskzone_list', + 'chapter': 'GENERAL', + 'auto_start': False, + 'order': 44, + 'roles': [11, 1, 6, 10, 7], + 'steps': [ + { + 'order': 1, 'step_key': 'zonetype-concepto', 'step_type': 'MODAL', + 'title': '¿Qué son los Tipos de Zona?', + 'content': 'El Tipo de Zona clasifica cada zona de riesgo según la naturaleza del peligro que representa. Esta clasificación determina los protocolos de seguridad, el equipo de protección personal requerido y las restricciones de acceso aplicables a cada área del laboratorio.', + }, + { + 'order': 2, 'step_key': 'zonetype-tipos', 'step_type': 'MODAL', + 'title': 'Tipos de zona disponibles', + 'content': 'Los tipos de zona de riesgo disponibles son: Química (manejo de sustancias químicas peligrosas), Biológica (agentes biológicos o patógenos), Inflamable (materiales o vapores inflamables), Almacenamiento (depósito de sustancias o materiales), Residuos (área de acopio de desechos) y Alto Tránsito (zonas con alta circulación de personas).', + }, + { + 'order': 3, 'step_key': 'zonetype-asignar', 'step_type': 'MODAL', + 'title': 'Asignar tipo al crear una zona', + 'content': 'Al registrar una nueva zona de riesgo, seleccione el tipo de zona que mejor describe el área. Esta clasificación aparece en los listados, reportes y mapas de riesgo, permitiendo identificar rápidamente la naturaleza del peligro de cada zona y aplicar las medidas de seguridad correspondientes.', + }, + { + 'order': 4, 'step_key': 'zonetype-impacto', 'step_type': 'MODAL', + 'title': 'Impacto en reportes y gestión', + 'content': 'El tipo de zona afecta directamente los reportes de zonas de riesgo y la compatibilidad SGA del área. Las zonas químicas e inflamables están sujetas a evaluación del Decreto 44741 de Costa Rica. Mantener el tipo correcto garantiza que los cálculos de riesgo y los reportes regulatorios sean precisos.', + }, + ], + }, + + # Gap 6: MSDS Gestión Detallada + { + 'title': 'Gestión Detallada de MSDS', + 'slug': 'msds-gestion-detallada', + 'description': 'Búsqueda con filtros, visualización completa, descarga y carga de nuevas hojas de seguridad', + 'url_name': 'msds:index_msds', + 'chapter': 'SUSTANCIAS', + 'auto_start': False, + 'order': 45, + 'roles': [1, 6, 10, 5, 13, 7], + 'steps': [ + { + 'order': 1, 'step_key': 'msdsdet-busqueda', 'step_type': 'MODAL', + 'title': 'Búsqueda con filtros avanzados', + 'content': 'La vista principal de MSDS permite filtrar hojas de seguridad por: nombre de la sustancia, código CAS, fuente (proveedor o institución de origen), fecha de revisión y última actualización. Ingrese el criterio, presione Buscar y seleccione el registro deseado.', + }, + { + 'order': 2, 'step_key': 'msdsdet-visualizar', 'step_type': 'MODAL', + 'title': 'Visualización completa de una MSDS', + 'content': 'Al seleccionar una hoja registrada, el sistema muestra su información general: nombre de la sustancia, código CAS, proveedor o fuente, fecha de emisión, fecha de revisión, versión y el archivo PDF adjunto disponible para descarga inmediata.', + }, + { + 'order': 3, 'step_key': 'msdsdet-descarga', 'step_type': 'MODAL', + 'title': 'Descargar una hoja de seguridad', + 'content': 'Para descargar una MSDS: seleccione el registro en la lista, presione el botón Descargar y el archivo se descargará automáticamente en formato PDF. Las hojas de seguridad son documentos legalmente requeridos que deben estar disponibles físicamente en el laboratorio para cualquier sustancia peligrosa.', + }, + { + 'order': 4, 'step_key': 'msdsdet-carga', 'step_type': 'MODAL', + 'title': 'Cargar una nueva hoja de seguridad', + 'content': 'Para registrar una nueva MSDS: seleccione Crear nuevo archivo SDS, presione Examinar para seleccionar el archivo PDF desde su equipo, complete los datos de la sustancia (nombre, CAS, fuente, fechas) y presione Guardar. La hoja quedará disponible para consulta de todos los usuarios con acceso al módulo.', + }, + { + 'order': 5, 'step_key': 'msdsdet-vencimiento', 'step_type': 'MODAL', + 'title': 'Control de versiones y vigencia', + 'content': 'Registre la fecha de revisión de cada MSDS para mantener el control de vigencia. Las hojas de seguridad deben actualizarse cuando el fabricante lanza una nueva versión o cuando cambian las propiedades o clasificación de la sustancia. El campo última actualización permite identificar rápidamente las hojas que requieren revisión.', + }, + ], + }, + + # Gap 7: SGA Etiquetas y Aplicación Física + { + 'title': 'Etiquetas SGA y Aplicación Física', + 'slug': 'sga-etiquetas-aplicacion', + 'description': 'Crear etiquetas SGA paso a paso y aplicarlas correctamente en el laboratorio', + 'url_name': 'sga:step_one', + 'chapter': 'SUSTANCIAS', + 'auto_start': False, + 'order': 46, + 'roles': [16, 1, 6, 10, 5, 14, 13], + 'steps': [ + { + 'order': 1, 'step_key': 'sgaetq-crear', 'step_type': 'MODAL', + 'title': 'Crear una nueva etiqueta SGA', + 'content': 'Para crear una etiqueta: seleccione Crear nueva etiqueta, ingrese el nombre de la sustancia o producto químico (ej: Ácido clorhídrico, Acetona) y seleccione la plantilla gráfica correspondiente. La plantilla define el formato visual de la etiqueta con su estructura de pictogramas y frases.', + }, + { + 'order': 2, 'step_key': 'sgaetq-plantilla', 'step_type': 'MODAL', + 'title': 'Seleccionar la plantilla correcta', + 'content': 'La plantilla determina qué elementos aparecerán en la etiqueta: pictogramas SGA (llama, calavera, signo de exclamación, etc.), palabra de advertencia (Peligro o Atención), frases H de peligro y frases P de prudencia. Seleccione la plantilla que corresponda a la clasificación de la sustancia.', + }, + { + 'order': 3, 'step_key': 'sgaetq-visualizar', 'step_type': 'MODAL', + 'title': 'Visualizar etiquetas registradas', + 'content': 'La lista principal muestra todas las etiquetas SGA registradas con su nombre, plantilla asignada, fecha de creación, estado y tipo de riesgo. Puede consultar el detalle de cada etiqueta para verificar que todos los elementos estén correctamente configurados antes de imprimirla y aplicarla.', + }, + { + 'order': 4, 'step_key': 'sgaetq-uso', 'step_type': 'MODAL', + 'title': 'Usos de las etiquetas SGA', + 'content': 'Las etiquetas generadas se utilizan para: identificación de reactivos en el inventario, etiquetado de contenedores de almacenamiento, señalización de zonas de riesgo, reportes de compatibilidad y cumplimiento del Decreto 44741. Una sustancia peligrosa sin etiqueta SGA es un incumplimiento regulatorio.', + }, + { + 'order': 5, 'step_key': 'sgaetq-aplicacion', 'step_type': 'MODAL', + 'title': 'Aplicación física en el laboratorio', + 'content': 'Las etiquetas SGA deben colocarse físicamente en: frascos y envases de reactivos, contenedores de almacenamiento, estantes donde se ubican sustancias peligrosas, zonas de almacenamiento de riesgo y recipientes de residuos. Imprima la etiqueta desde el sistema y péguela de forma visible y duradera.', + }, + ], + }, + + # Gap 8: Clasificación y Consulta de Desechos + { + 'title': 'Clasificación y Consulta de Desechos', + 'slug': 'desechos-clasificacion-consulta', + 'description': 'Tipos de clasificación de desechos, consulta por laboratorio y ubicación física del residuo', + 'url_name': 'laboratory:disposal_substance', + 'chapter': 'LABORATORIOS', + 'auto_start': False, + 'order': 47, + 'roles': [13, 14, 1, 6, 10, 8], + 'steps': [ + { + 'order': 1, 'step_key': 'desclass-tipos', 'step_type': 'MODAL', + 'title': 'Clasificación del desecho', + 'content': 'Cada desecho debe clasificarse según su naturaleza. Los tipos disponibles son: Reactivos vencidos (sustancias fuera de fecha de caducidad), Materiales contaminados (utensilios o equipos con residuos), Residuos químicos (sobrantes de reacciones o procesos), Sustancias precursoras (con control regulatorio especial) y Residuos peligrosos (con riesgo para la salud o el ambiente).', + }, + { + 'order': 2, 'step_key': 'desclass-lista', 'step_type': 'MODAL', + 'title': 'Vista principal de desechos', + 'content': 'La pantalla principal muestra la lista de sustancias desechadas con: laboratorio, sustancia o reactivo, cantidad restante, ubicación (sala/estante/contenedor), estado y fecha de registro. Desde aquí puede consultar el detalle de cada desecho y filtrar por laboratorio para ver solo los residuos de un área específica.', + }, + { + 'order': 3, 'step_key': 'desclass-ubicacion', 'step_type': 'MODAL', + 'title': 'Ubicación física del desecho', + 'content': 'El sistema registra la ubicación exacta de cada residuo: laboratorio → sala → mueble → estante → contenedor. Esta información es clave para los procesos de recolección y disposición final. La empresa gestora de residuos puede usar esta información para identificar y retirar los materiales de forma eficiente.', + }, + { + 'order': 4, 'step_key': 'desclass-consulta', 'step_type': 'MODAL', + 'title': 'Consulta por laboratorio', + 'content': 'La información de desechos se organiza por laboratorio, lo que permite: control por unidad académica o de investigación, auditoría interna de residuos generados, gestión ambiental por sede y control de residuos acumulados. Use los filtros para ver solo el laboratorio de interés.', + }, + { + 'order': 5, 'step_key': 'desclass-integracion', 'step_type': 'MODAL', + 'title': 'Integración con otros módulos', + 'content': 'El módulo de Desechos se integra directamente con: Reactivos (origen del desecho), SGA (clasificación de peligrosidad), MSDS (procedimientos de disposición segura), Zonas de Riesgo (área donde se genera el residuo), Reportes (informe de desechos) y Movimientos de Objetos (trazabilidad del traslado al área de descarte).', + }, + ], + }, + + # Gap 9: Operaciones Avanzadas de Inventario + { + 'title': 'Operaciones Avanzadas de Inventario', + 'slug': 'operaciones-avanzadas-inventario', + 'description': 'Bitácora del reactivo, administración de contenedor, mover estante, descarga de información y sustracción', + 'url_name': 'laboratory:rooms_list', + 'chapter': 'LABORATORIOS', + 'auto_start': False, + 'order': 48, + 'roles': [1, 6, 10, 5, 15, 13, 14, 8], + 'steps': [ + { + 'order': 1, 'step_key': 'opinv-bitacora', 'step_type': 'MODAL', + 'title': 'Bitácora del reactivo', + 'content': 'Cada reactivo en estante tiene una bitácora completa que registra el historial de todos sus movimientos y cambios. La bitácora incluye: acción realizada (ingreso, consumo, transferencia, etc.), descripción, fecha del evento, usuario responsable y estado actualizado. Es la fuente de trazabilidad completa del reactivo.', + }, + { + 'order': 2, 'step_key': 'opinv-contenedor', 'step_type': 'MODAL', + 'title': 'Administración de contenedor', + 'content': 'La opción Administrar contenedor permite gestionar el envase físico donde está el reactivo. Las acciones disponibles son: usar el contenedor actual (ya registrado), crear un nuevo contenedor (registrar un envase nuevo) o asociar un contenedor existente al reactivo. Esto permite rastrear en qué frasco o recipiente físico está almacenada la sustancia.', + }, + { + 'order': 3, 'step_key': 'opinv-mover', 'step_type': 'MODAL', + 'title': 'Mover a otro estante', + 'content': 'La opción Mover permite reubicar un reactivo dentro del mismo laboratorio sin crear una transferencia. Seleccione la nueva sala, el mueble, el estante y el contenedor destino. El movimiento queda registrado en la bitácora con el usuario y la fecha para mantener la trazabilidad de la ubicación física.', + }, + { + 'order': 4, 'step_key': 'opinv-descarga', 'step_type': 'MODAL', + 'title': 'Descarga de información del reactivo', + 'content': 'La opción Descargar genera un reporte detallado del reactivo con: nombre, cantidad, estado físico, fecha de caducidad, contenedor, fórmula molecular, código CAS, biocumulable, tipo de almacenamiento, si es precursor y descripción general. Útil para inventarios físicos y auditorías.', + }, + { + 'order': 5, 'step_key': 'opinv-sustraer', 'step_type': 'MODAL', + 'title': 'Sustracción de reactivos', + 'content': 'La opción Sustraer descuenta una cantidad del stock actual del reactivo. Campos requeridos: cantidad a descontar, descripción del motivo de la sustracción (uso, derrame, vencimiento, etc.) y unidad de medida. El stock se actualiza automáticamente y el movimiento queda registrado en la bitácora con el usuario responsable.', + }, + ], + }, + + # Gap 11: Tutoriales y Documentación del Sistema + { + 'title': 'Tutoriales y Documentación del Sistema', + 'slug': 'tutoriales-documentacion-sistema', + 'description': 'Módulo de consulta de tutoriales, manuales, reglamentos y documentación institucional', + 'url_name': 'laboratory:labindex', + 'chapter': 'GENERAL', + 'auto_start': False, + 'order': 49, + 'roles': [11, 1, 6, 10, 4, 5, 13, 14, 15, 7, 8, 16], + 'steps': [ + { + 'order': 1, 'step_key': 'tutdoc-concepto', 'step_type': 'MODAL', + 'title': 'Módulo de Tutoriales y Documentación', + 'content': 'El módulo Tutoriales y Documentación centraliza los recursos de apoyo del sistema. Desde aquí puede acceder a tutoriales de uso por módulo (guías paso a paso), guías rápidas de consulta, documentación formal cargada por la organización, reglamentos institucionales y manuales internos.', + }, + { + 'order': 2, 'step_key': 'tutdoc-tutoriales', 'step_type': 'MODAL', + 'title': 'Sección de Tutoriales', + 'content': 'La opción Tutoriales muestra guías interactivas sobre el uso de los diferentes módulos del sistema. Cada tutorial explica dónde se encuentra el módulo, qué funciones posee y qué acciones se pueden realizar. Se recomienda consultar esta sección cuando necesite aprender a usar una función nueva o validar el flujo de un proceso.', + }, + { + 'order': 3, 'step_key': 'tutdoc-documentacion', 'step_type': 'MODAL', + 'title': 'Sección de Documentación', + 'content': 'La opción Documentación permite consultar toda la información formal cargada en el sistema. Esta sección puede incluir: manuales de usuario, procedimientos internos, instructivos, normativas institucionales y documentos de respaldo. Los documentos pueden visualizarse y descargarse según los permisos asignados.', + }, + { + 'order': 4, 'step_key': 'tutdoc-reglamentos', 'step_type': 'MODAL', + 'title': 'Reglamentos institucionales', + 'content': 'Dentro de Documentación puede consultar los reglamentos institucionales relacionados con: seguridad en el laboratorio, uso de instalaciones, manejo de sustancias, gestión de residuos, acceso de usuarios y normas operativas. Mantener estos reglamentos actualizados en el sistema garantiza que todo el personal los tenga disponibles.', + }, + ], + }, +] + + +def load_tutorials(apps, schema_editor): + Tutorial = apps.get_model('presentation', 'Tutorial') + TutorialStep = apps.get_model('presentation', 'TutorialStep') + Rol = apps.get_model('auth_and_perms', 'Rol') + + for tdata in TUTORIALS: + tutorial = Tutorial.objects.create( + title=tdata['title'], + slug=tdata['slug'], + description=tdata['description'], + url_name=tdata['url_name'], + chapter=tdata['chapter'], + auto_start=tdata['auto_start'], + order=tdata['order'], + is_active=True, + ) + + if tdata['roles']: + roles = Rol.objects.filter(pk__in=tdata['roles']) + tutorial.target_roles.set(roles) + + for sdata in tdata['steps']: + TutorialStep.objects.create( + tutorial=tutorial, + order=sdata['order'], + step_key=sdata['step_key'], + title=sdata['title'], + content=sdata['content'], + step_type=sdata['step_type'], + css_selector=sdata.get('css_selector', ''), + position=sdata.get('position', 'bottom'), + action_url=sdata.get('action_url', ''), + ) + + +def remove_tutorials(apps, schema_editor): + Tutorial = apps.get_model('presentation', 'Tutorial') + slugs = [t['slug'] for t in TUTORIALS] + Tutorial.objects.filter(slug__in=slugs).delete() + + +class Migration(migrations.Migration): + + dependencies = [ + ('presentation', '0010_fix_salas_muebles_url'), + ('auth_and_perms', '0026_remove_unused_roles'), + ] + + operations = [ + migrations.RunPython(load_tutorials, remove_tutorials), + ]