GUÍA DOCENTE - ISPC-WEB-2025/TodoStock-AppMovil GitHub Wiki

🎓 Guía de aclaraciones

Este documento ha sido elaborado a solicitud del docente para sintetizar el funcionamiento integral, las decisiones de arquitectura, las credenciales de prueba y la localización de los principales artefactos del proyecto TodoStock, desarrollado por el equipo CodeLab.


📌 1. Accesos Rápidos, Entornos Desplegados y Credenciales Demo

Para facilitar la corrección y prueba del sistema en sus distintas capas (Web, API REST, Admin Panel y App Mobile), se detallan a continuación los entornos activos en producción y las cuentas de prueba configuradas:

🌐 Entornos en Producción

Componente Plataforma URL Pública Repositorio GitHub
Frontend Web (SPA Angular 21) Vercel https://todo-stock.vercel.app/ TodoStock Repo
Backend REST API (Django 6) Alwaysdata https://todostock.alwaysdata.net/api/ TodoStock Repo
Panel de Administración Django Alwaysdata https://todostock.alwaysdata.net/admin/ TodoStock Repo
Aplicación Móvil (Android Java) Google Play / APK Release v1.0.0 en GitHub TodoStock-AppMovil Repo
Roadmap Interactivo del Proyecto GitHub Pages https://ispc-web-2025.github.io/TodoStock-Mobile-RoadMap/ TodoStock-AppMovil Repo

🔐 Credenciales Demo (Desarrollo y Producción)

Para la evaluación del sistema completo se proveen las credenciales de acceso:

  • Cuenta Principal SuperAdministrador (API / Django Admin / App / Web):

    • Email / Usuario: [email protected]
    • Contraseña: AdminPassword123!
    • Rol: ADMINISTRADOR (is_superuser=True, is_staff=True)
    • Permisos: Acceso completo a la API, Panel Django Admin, Dashboard Web y la Aplicación Móvil Android.
  • Acceso al Roadmap Interactivo (GitHub Pages):


🛡️ 2. Jerarquía de Autenticación y SuperAdministrador Django (ADR-0008)

Para responder a las observaciones sobre seguridad y niveles de acceso en el sistema, se implementó un control de acceso basado en roles (RBAC) con tres niveles de privilegio claramente definidos:

  1. Jerarquía y Matriz de Permisos Administrativos:
    • 👑 SuperAdministrador (is_superuser=True): Posee control total del sistema. Es el único rol habilitado para:
      • Crear nuevas cuentas de nivel Administrador.
      • Aprobar/aceptar solicitudes de registro pendientes de usuarios con rol Administrador.
      • Editar perfiles, reasignar roles, resetear contraseñas o desactivar a otros usuarios administradores.
      • Gestionar en forma global a administradores y empleados.
    • 👔 Administrador Estándar (rol = ADMINISTRADOR, is_superuser=False):
      • Permiso acotado: Puede aprobar solicitudes pendientes y editar perfiles únicamente de usuarios con rol Empleado (es_empleado).
      • Restricción de seguridad: La API le bloquea de forma estricta cualquier intento de crear administradores, aprobar solicitudes pendientes de rol Administrador o editar perfiles de otros administradores, devolviendo HTTP 403 Forbidden.
      • Gestiona sucursales, productos del catálogo, existencias de inventario y traslados.
    • 👷 Empleado / Vendedor (es_empleado=True):
      • Acceso operativo para consulta de stock, traslados entre sucursales, consulta de catálogo y soporte.
  2. Exposición en API (/api/usuarios/me/):
    • El payload del usuario autenticado expone los flags is_superuser y es_empleado, permitiendo que tanto la Web como la App Móvil muestren la distintiva insignia visual (Super Admin vs Administrador vs Empleado).
  3. Desacople de Gestión de Contraseñas:
    • Se eliminó el cambio de clave desde peticiones PUT generales. Se dispuso el endpoint de autoservicio POST /api/usuarios/me/change-password/ (requiere password_actual) y el endpoint restringido POST /api/usuarios/<id>/reset-password/ para reset administrativo de empleados.

👥 3. Unificación Operativa de Roles a Empleado (es_empleado) (ADR-0007)

Contexto y Problema Detectado en Clase

En la operatoria real de sucursales y depósitos, los colaboradores alternan constantemente entre la atención al público (ventas) y la logística interna (conteo de stock, recepción y traslado de mercadería). Exigir cuentas o perfiles separados para "Vendedor" y "Personal de Depósito" generaba una alta fricción UX (cierres y aperturas constantes de sesión en los dispositivos móviles).

Solución Arquitectónica Implementada

  1. Preservación Físico-Relacional en MySQL:
    • No se eliminaron ni fusionaron los roles en la base de datos. La tabla roles mantiene los registros independientes: ADMINISTRADOR, VENTAS y DEPOSITO. Esto evita migraciones de BD destructivas y pérdida de historial.
  2. Abstracción Lógica en la API (es_empleado):
    • El backend Django expone una propiedad calculada @property es_empleado en los endpoints de autenticación:
      @property
      def es_empleado(self):
          return self.rol is not None and self.rol.nombre.lower() in [
              "empleado",
              "ventas",
              "deposito",
          ]
  3. Consumo Unificado en App Móvil:
    • La app Android evalúa es_empleado para habilitar el menú de herramientas operativas (búsqueda de catálogo, escáner, control de existencias y registro de traslados).
  4. Preparación Transparente a Futuro:
    • Si en fases posteriores se decide activar permisos restrictivos (ej. alta de mercadería reservada solo a depósito), el cliente móvil simplemente evaluará el objeto user.rol.nombre directamente, sin requerir ningún cambio de esquema en MySQL.

⚡ 4. Configuración de Throttling en Pruebas Automatizadas (CI/CD)

Contexto y Decisión Técnica

Durante la validación automática de la suite de pruebas del backend en la integración continua (CI/CD ejecutado en Python 3.12 y MySQL 8.0 ante cada Pull Request hacia develop o main), se identificó una falla por respuestas HTTP 429 Too Many Requests.

  1. Causa Raíz:
    • La suite de pruebas ejecuta tests masivos e instantáneos de autenticación e inicio de sesión.
    • La falla demostró que la política de limitación de tasa (throttling) de Django REST Framework en la API funciona correctamente al bloquear peticiones consecutivas en lapsos de tiempo cortos.
  2. Evaluación de Alternativas:
    • Opción A (Descartada): Introducir pausas temporales (sleep) entre intentos de login en las pruebas. Se descartó debido a que volvía las pruebas CI/CD extremadamente lentas.
    • Opción B (Adoptada): Configurar dinámicamente DEFAULT_THROTTLE_RATES para desactivar el throttling exclusivamente durante la ejecución de la suite de tests.
  3. Conclusión:
    • Aunque no es el escenario ideal para el entorno de tests, se verificó primero que el mecanismo de protección throttling está completamente operativo en la API. Se optó por desactivarlo dinámicamente en los tests para evitar ejecuciones lentas y falsos negativos en el pipeline de GitHub Actions.

📐 5. Referencias a Diagramas de Arquitectura y Diseño

💡 Observaciones Clave sobre los Diagramas (Criterio de Diseño y Evolución del Backlog)

Para una correcta interpretación de los diagramas UML, DER y el modelo relacional frente a la implementación final en la aplicación móvil y la API:

  1. Unificación Operativa de Roles (Modelo Relacional vs. App Mobile — ADR-0007 y ADR-0008):

    • En la base de datos (MySQL / DER): Se preservan los tres roles relacionales normalizados: ADMINISTRADOR, VENTAS y DEPOSITO en la tabla roles.
    • En la App Mobile: Al no haberse desarrollado un flujo exclusivo para el rol de depósito en la app, se decidió por simplicidad funcional unificarlo con el de vendedor bajo la abstracción @property es_empleado (rol operativo "Empleado"). Para la administración, se diferencia al SuperAdministrador (is_superuser=True) frente al Administrador estándar para el control de altas y permisos.
  2. Comportamiento en Eliminación de Productos y Stock Inicial (Issue #282 / ADR-0010):

    • En el backend actual, al crear un producto nuevo se generan automáticamente registros de stock en cero en todas las sucursales. Esto provocaba que el endpoint DELETE del backend bloqueara la eliminación física al detectar registros asociados en la tabla de stock (reportado en Issue #282).
    • Al detectarse cerca del cierre del sprint, se decidió no arriesgar la estabilidad del backend en producción y resolver el manejo desde el frontend mediante baja lógica (activo = False), dejando documentada la refactorización para futuras versiones.
  3. Desactivación de Usuarios y Anonimización Pendiente (ADR-0009 / Ley 25.326):

    • La baja de cuenta (voluntaria o administrativa) actualmente desactiva al usuario marcando is_active = False para bloquear el inicio de sesión (HTTP 403), conservando el registro histórico para auditoría en LogAuditoria.
    • La anonimización completa de los datos personales (nombre, email, DNI) quedó documentada como un Issue en el backlog para próximas etapas, al tratarse del sprint final de la materia.

📚 6. Guía de Documentación Técnica en Repositorio TodoStock

En la carpeta Docs/ de TodoStock se centralizan las especificaciones técnicas de la API REST y las guías de infraestructura:

  1. 📄 API_MOBILE.md:
    • Especificación detallada de endpoints consumidos por la aplicación Android, estructuras JSON de solicitud/respuesta, encabezados JWT y códigos de estado HTTP.
  2. 🏛️ Registros de Decisiones de Arquitectura (ADR):
    • ADR-0001: Filtrado de movimientos en servidor.
    • ADR-0002: Registro dual de traslados entre sucursales.
    • ADR-0003: Desacople de operador en movimientos.
    • ADR-0004: Enforcement global de autenticación JWT.
    • ADR-0005: Sucursal central y distribución jerárquica.
    • ADR-0006: Arquitectura de consumo de backend desde App Mobile.
    • ADR-0007: Unificación operativa de roles Vendedor/Depósito en es_empleado.
    • ADR-0008: Blindaje de jerarquía administrativa y SuperAdmin.
    • ADR-0009: Modelo de log de auditoría desacoplado.
    • ADR-0010: Baja lógica de productos (activo = False) preservando trazabilidad.
  3. 🚀 Guías de Despliegue y Pruebas:

7. Aclaración sobre la ejecución de los casos de prueba

Algunos casos del Sprint 1 y del Sprint 2 fueron ejecutados por la misma persona que desarrolló la funcionalidad, por falta de tiempo. Cada uno lo indica en la columna Comentarios de la planilla de test cases.

Casos alcanzados: TC-L-03, TC-L-04 (Login), TC-SSUC-01, TC-SSUC-02 (Selección de sucursal), TC-MOV-001 a TC-MOV-007 (Movimientos), TC-CP-01 (Carga de producto), TC-C-01 (Contacto), TC-STK-001 (Stock), TC-REG-EDAD-01, TC-REG-EDAD-02 (Registro) y TC-SEG-05 (Seguridad). El bug #183 (TC-MOV-007) fue corregido y cerrado por la misma persona que lo reportó.

Para el resto del Sprint 2, las ejecuciones (TK85 a TK89) se reasignaron para que nadie ejecute casos de una funcionalidad que programó. Los casos nuevos del Registro (TC-REG-01 a 04) los diseñan y ejecutan personas distintas de quien lo programó.

Los tests automatizados (ValidadoresTest) los escribe y ejecuta quien desarrolló el código, como es habitual en las pruebas unitarias.


8. Análisis Auditado de Integración Móvil-Backend y Trazabilidad de GitHub Issues/PRs

🔄 8.1 Matriz de Mapeo de Endpoints (Backend Django REST ➔ App Móvil Android)

A partir del análisis del Docs/API_MOBILE.md y Backend/ en contraste con los servicios Retrofit implementados en la app Android nativa, se certifica el acoplamiento al 100% de los siguientes contratos HTTP:

Módulo / Feature Endpoint Backend Django (Backend/) Verbo HTTP Servicio Android / DTOs PR Integración
Autenticación JWT /api/usuarios/login/ POST AuthApiService / LoginRequest, LoginResponse PR #49, PR #160
Registro de Usuarios /api/usuarios/registro/ POST AuthApiService / RegistroRequest, RegistroResponse PR #171, PR #173, PR #223, PR #283
Datos de Sesión / Perfil /api/usuarios/me/ GET/PATCH PerfilApiService / PerfilResponse, PerfilUpdateRequest PR #180
Baja de Cuenta (Desactivar) /api/usuarios/desactivar/ POST PerfilApiService / BajaRequest PR #195
Listado de Sucursales /api/inventario/sucursales/ GET InventarioApiService / SucursalDto PR #185
Stock por Sucursal /api/inventario/productos/{id}/stock/ GET InventarioApiService / StockItemResponse PR #216, PR #220
Alta de Producto (Admin) /api/inventario/productos/ POST InventarioApiService / ProductoCreateDto PR #197, PR #287
Catálogo y Edición (Admin) /api/inventario/productos/ / {id}/ GET/PATCH InventarioApiService / ProductoDto PR #296 (TK39 / ADR-0010)
Movimiento Atómico Stock /api/inventario/movimientos/ POST InventarioApiService / MovimientoRequest PR #185 (ADR-0002)
Gestión de Usuarios (Admin) /api/usuarios/ / {id}/ GET/PATCH UsuarioApiService / UsuariosActivosFragment PR #300 (TK37 / ADR-0008)
Contacto y Soporte /api/contacto/ POST ContactoApiService / ContactoRequest PR #192

🏛️ 8.2 Trazabilidad de Registros de Decisiones de Arquitectura (ADRs Docs/ADR/)

  1. ADR-0001 (Filtrado en Servidor): El cliente Android delega el cálculo de movimientos y stock consolidado a la API Django REST para optimizar consumo de batería y datos móviles.
  2. ADR-0002 (Registro Dual de Traslados): Cada transferencia de stock enviada desde MovimientosActivity genera en la base de datos MySQL de forma atómica una salida en la sucursal origen y una entrada en la sucursal destino.
  3. ADR-0004 (Enforcement Global JWT): Validado mediante AuthInterceptor en OkHttp, inyectando la cabecera Authorization: Bearer <token> en todas las peticiones excepto Login, Registro y Contacto.
  4. ADR-0007 (Unificación Operativa es_empleado): La app evalúa la propiedad calculada @property es_empleado expuesta en /api/usuarios/me/ para habilitar el panel operativo único.
  5. ADR-0008 (Blindaje Jerárquico Admin/SuperAdmin): Reflejado en las insignias de perfil de PerfilActivity, en UsuariosActivosFragment (PR #300) y restricción de endpoints administrativos (HTTP 403 Forbidden).
  6. ADR-0009 (Modelo LogAuditoria): Cada acción crítica (baja de cuenta, registro, movimiento) se registra de forma desacoplada en la tabla LogAuditoria en MySQL.
  7. ADR-0010 (Baja Lógica de Productos): Eliminación lógica (activo = False) preservando el historial de transacciones en la base de datos MySQL.

🐛 8.3 Reporte de Defectos Corregidos y Calidad CI/CD

Contrastando el código fuente con el registro de Issues:

  • Bugs de Registro (#167, #168, #169, #281): Resueltos mediante PRs #171, #173, #223, #283 incorporando la validación en cliente Validadores.java, el ingreso directo por teclado con máscara en RegistroActivity y manejando respuestas HTTP 400/409 del backend.
  • Bug de Traslados (#183 - TC-MOV-007): Resuelto en PR #185 corrigiendo la validación de stock disponible antes del envío de la petición POST /api/inventario/movimientos/.
  • Pipeline CI/CD Backend (.github/workflows/django-tests.yml): Ejecutado en Python 3.12 con MySQL 8.0, validando la suite de 729 líneas en Backend/usuarios/tests.py y 226 líneas en Backend/inventario/test_mobile_api.py.

🎨 8.4 Reestructuración UX, Adaptabilidad, Aprobaciones y Testing Automatizado (PRs #267, #275..#301)

  • Módulo de Ayuda e Información de App (TK40 - PR #301): Implementación de AyudaActivity, reproductor de video tutorial adaptativo sin barras negras en ComoUsarActivity (VideoView con preservación de segundo actual al rotar vía onSaveInstanceState) e información técnica del sistema en InfoAppActivity leyendo dinámicamente la versión desde BuildConfig.VERSION_NAME.
  • Gestión, Edición y Baja de Usuarios (TK37 - PR #300): Implementación en UsuariosActivosFragment y UsuarioApiService con diálogo modal para edición de datos y baja de usuarios respetando la jerarquía RBAC (ADR-0008).
  • Pruebas de UI con Espresso y Page Objects (AUT-UI-01 - TK70 - PR #299): Automatización del flujo completo desde Login hasta el Menú Principal en LoginFlujoTest.java utilizando Page Object Model (LoginScreen, MenuPrincipalScreen), AccessibilityChecks.enable() e IdlingResource.
  • Suite Postman de Integración de API (AUT-API-02 - TK68 - PR #298): Implementación de la colección de integración de catálogo de productos e infraestructura utilitaria en PostmanConfig.java.
  • Listado, Búsqueda, Edición y Baja Lógica de Productos (TK39 - PR #296): Módulo de catálogo completo con precarga en CargaProductoActivity (EXTRA_ID_PRODUCTO), actualización parcial PATCH e inhabilitación lógica (activo = False - ADR-0010).
  • Testing de Red con MockWebServer 200 OK y Error 500 (AUT-NET-02 - TK65 - PR #295, PR #297): Implementación de AuthRepositoryTest.java para verificar autenticación, respuesta 200 OK, captura de fallos de servidor HTTP 500 e inestabilidad de red en ResultadoLogin.
  • Aprobación y Carga de Usuarios (TK109 - PR #290): Implementación de CargarUsuarioFragment para la aprobación de cuentas de registro pendientes según la jerarquía RBAC (SuperAdmin aprueba Admins; Admin aprueba Empleados).
  • Adaptabilidad a Pantalla Apaisada y Tablet (TK41 - PR #294): Adaptación de 11 layouts XML con ScrollView, márgenes ajustados, centrado de botones y preservación de estado de Spinners al rotar mediante onSaveInstanceState.
  • Testing Unitario de ViewModel (TK62 - PR #293): Incorporación de LoginViewModelTest.java para la verificación aislada de estados de inicio de sesión con repositorio simulado.
  • Testing de Integración de Red con MockWebServer (TK64 - PR #292): Implementación de ParseoRespuestasTest.java para la simulación de servidor REST HTTP 200 OK y parseo de DTOs JSON.
  • Alta de Producto con Categoría (TK23 - PR #287): Selección e integración de categoría de producto enviada a la API REST en CargaProductoActivity.
  • Refuerzo de Testing Unitario Android (TK60 / TK61 - PR #267, PR #277): Incorporación de StockItemTest.java para validaciones de stock bajo umbral y mappers DTO, eliminando los tests de plantilla genéricos de Android Studio.
  • Ingreso Directo de Fecha por Teclado (Fix #281 - PR #283): Entrada de fecha sin modal en RegistroActivity mediante máscara de texto DD/MM/AAAA.
  • Pantallas Intermedias / Hubs Operativos (TK113 - PR #276): Integración de MenuStockActivity y MenuMovimientosActivity.
  • Reorganización del Menú Principal (TK114 - PR #275): Layout vertical accesible sin numeración estática en MenuPrincipalActivity.
⚠️ **GitHub.com Fallback** ⚠️