Análisis: Diseño e Implementación de una Aplicación de Gestión con Flask y MySQL
Autor: Andrés Rojas, IA
1. Introducción
El objetivo de este documento es presentar un análisis técnico del desarrollo de una aplicación web para la gestión de un catálogo de productos, utilizando Python con el framework Flask para el backend y una base de datos MySQL. A diferencia de un tutorial convencional, este artículo se centra en el proceso de derivar requerimientos funcionales a partir de un problema de negocio, definir reglas operativas, y traducir todo ello en una arquitectura de software coherente y funcional.
El análisis se basa en la estructura y lógica de proyectos de referencia como CAC-PythonFS-Back y CAC-PythonFS-Front, aplicados a un caso de estudio concreto: un sistema de gestión para una ferretería. Se detallarán el modelo de datos, las historias de usuario que definen el alcance y los casos de uso que describen la interacción del sistema.
2. Análisis del Problema y Reglas de Negocio
El punto de partida es un problema de negocio común: una ferretería necesita un sistema centralizado para administrar su catálogo de productos, proveedores y categorías. Actualmente, este proceso puede ser manual, propenso a errores y difícil de escalar. La solución propuesta debe automatizar y estructurar esta gestión.
De este problema se derivan las siguientes reglas de negocio que el software debe implementar:
-
Integridad de Datos: El sistema debe asegurar que cada producto esté asociado a una categoría y un proveedor válidos. Si una de estas entidades es eliminada, el producto debe permanecer en el sistema pero con una referencia nula (
ON DELETE SET NULL), evitando la pérdida de datos del producto. -
Gestión de Catálogo Centralizada: Todas las operaciones de creación, lectura, actualización y eliminación (CRUD) de productos, categorías y proveedores deben realizarse a través de una interfaz de administración o una API segura.
-
Importación Masiva de Datos: Para facilitar la carga inicial y las actualizaciones masivas, el sistema debe permitir la importación de productos desde un archivo Excel (
.xlsx). -
Flexibilidad en la Importación: El proceso de importación debe ser capaz de interpretar diferentes nombres de columnas en el archivo Excel (p. ej., "Art.", "Artículo", "art" deben ser mapeados al campo
artdel producto). -
Creación Automática de Entidades: Si durante la importación se encuentra un producto con una categoría o un proveedor que no existen en la base de datos, el sistema debe crearlos automáticamente para no interrumpir el proceso.
-
Prevención de Duplicados: Durante la importación, el sistema debe verificar si un producto ya existe en la base de datos (comparando por código de artículo o código de proveedor) para prevenir la duplicación de registros.
3. Modelo Conceptual del Sistema
Antes de implementar la solución técnica, es necesario definir el modelo conceptual que representa los elementos del dominio del negocio y sus interrelaciones.
3.1 Entidades Principales
El sistema de gestión de productos para una ferretería identifica las siguientes entidades principales:
Producto (product)
Representa un artículo disponible en el catálogo de la ferretería. Cada producto tiene un identificador único, un código de artículo, un código de proveedor, un título descriptivo y una descripción detallada. El producto es la entidad central del sistema, ya que agrupa información de múltiples dominios: la clasificación (categoría), el origen (proveedor) y la presentación visual (imagen).
Atributos:
id: Identificador único (clave primaria).art: Código de artículo interno de la ferretería.cod: Código del producto según el proveedor.tit: Título o nombre corto del producto.desc: Descripción detallada del producto.cat_id: Referencia a la categoría del producto (clave foránea).prov_id: Referencia al proveedor del producto (clave foránea).img_id: Referencia a la imagen del producto (clave foránea).
Categoría (category)
Representa una clasificación lógica bajo la cual se agrupan los productos. Las categorías facilitan la navegación y la búsqueda en el catálogo. Ejemplos incluyen "Herramientas", "Materiales de Construcción", "Pintura", etc.
Atributos:
id: Identificador único (clave primaria).name: Nombre de la categoría.unit: Unidad de medida estándar para los productos de esta categoría (p. ej., "metros", "kilogramos", "unidades").
Proveedor (prov)
Representa una empresa o entidad que suministra productos a la ferretería. Cada proveedor tiene un código identificador único y un nombre. El proveedor es fundamental para la gestión de compras y para rastrear el origen de los productos.
Atributos:
id: Identificador único (clave primaria).cod: Código del proveedor (puede ser un código interno o externo).name: Nombre del proveedor.
Imagen (image)
Representa la referencia a una imagen visual del producto. Aunque es una entidad separada, su propósito es almacenar la URL de la imagen y un texto alternativo para accesibilidad.
Atributos:
id: Identificador único (clave primaria).url_img: URL de la imagen del producto.txt_alt: Texto alternativo para la imagen (usado en lectores de pantalla y cuando la imagen no carga).
3.2 Relaciones entre Entidades
Las relaciones definen cómo las entidades se conectan entre sí. En este sistema, todas las relaciones son de tipo N:1 (muchos a uno), donde N representa la tabla product y 1 representa las otras tablas.
Relación: Producto - Categoría
- Cardinalidad: N:1 (muchos productos pueden pertenecer a una categoría, pero cada producto pertenece a una única categoría).
- Descripción: Un producto debe estar clasificado en exactamente una categoría. Una categoría puede contener cero o muchos productos.
- Implementación: La tabla
productcontiene la columnacat_idcomo clave foránea que referencia acategory.id. - Regla de Integridad: Si una categoría es eliminada, los productos asociados mantienen su referencia como nula (
ON DELETE SET NULL), preservando el registro del producto.
Relación: Producto - Proveedor
- Cardinalidad: N:1 (muchos productos pueden provenir de un proveedor, pero cada producto tiene un único proveedor).
- Descripción: Un producto debe estar asociado a exactamente un proveedor. Un proveedor puede suministrar cero o muchos productos.
- Implementación: La tabla
productcontiene la columnaprov_idcomo clave foránea que referencia aprov.id. - Regla de Integridad: Si un proveedor es eliminado, los productos asociados mantienen su referencia como nula (
ON DELETE SET NULL).
Relación: Producto - Imagen
- Cardinalidad: N:1 (muchos productos pueden compartir la misma imagen, pero cada producto tiene una única imagen asociada).
- Descripción: Un producto puede tener una imagen asociada. Una imagen puede ser utilizada por cero o muchos productos (aunque en la práctica, cada producto suele tener su propia imagen).
- Implementación: La tabla
productcontiene la columnaimg_idcomo clave foránea que referencia aimage.id. - Regla de Integridad: Si una imagen es eliminada, los productos asociados mantienen su referencia como nula (
ON DELETE SET NULL).
3.3 Diagrama Conceptual
La siguiente representación textual muestra las entidades y sus relaciones:
┌──────────────┐ ┌──────────────┐
│ CATEGORY │ │ PROV │
├──────────────┤ ├──────────────┤
│ id (PK) │ │ id (PK) │
│ name │ │ cod │
│ unit │ │ name │
└──────────────┘ └──────────────┘
▲ ▲
│ (1) │ (1)
│ │
│ cat_id prov_id
│ │
│ (N) │ (N)
│ │
┌───────┴────────────────────────┴────────┐
│ PRODUCT │
├─────────────────────────────────────────┤
│ id (PK) │
│ art │
│ cod │
│ tit │
│ desc │
│ cat_id (FK → CATEGORY) │
│ prov_id (FK → PROV) │
│ img_id (FK → IMAGE) │
└─────────────────────────────────────────┘
▲
│ (1)
│
│ img_id
│
│ (N)
│
┌───────┴──────────┐
│ IMAGE │
├──────────────────┤
│ id (PK) │
│ url_img │
│ txt_alt │
└──────────────────┘
4. Proceso de Diseño de la Base de Datos
El diseño de la base de datos es un proceso metódico que traduce los requerimientos del negocio en una estructura técnica robusta y eficiente. Este proceso sigue una serie de fases bien definidas que garantizan que la base de datos resultante sea coherente, escalable y capaz de soportar las operaciones del sistema.
4.1 Fase 1: Análisis de Requerimientos
La primera fase consiste en recopilar y analizar los requerimientos funcionales y no funcionales del sistema. En este caso, los requerimientos clave son:
- Funcionales: Gestionar un catálogo de productos, permitir la importación masiva desde Excel, prevenir duplicados, crear automáticamente categorías y proveedores.
- No Funcionales: El sistema debe ser escalable, permitir búsquedas rápidas, mantener la integridad de datos incluso cuando se eliminan entidades relacionadas.
A partir de estos requerimientos, se identifican las preguntas clave que la base de datos debe responder:
- ¿Cuáles son los atributos esenciales de un producto?
- ¿Cómo se relacionan los productos con categorías, proveedores e imágenes?
- ¿Qué información se necesita para prevenir duplicados?
- ¿Cómo se debe comportar el sistema cuando se elimina una categoría o proveedor?
4.2 Fase 2: Modelado Conceptual
En esta fase, se crea un modelo conceptual que representa el dominio del negocio de forma abstracta, sin considerar detalles técnicos. El modelo identifica las entidades principales, sus atributos y las relaciones entre ellas.
Identificación de Entidades:
Del análisis de requerimientos emergen cuatro entidades principales:
- Producto: La entidad central que representa los artículos del catálogo.
- Categoría: Agrupa los productos en clasificaciones lógicas.
- Proveedor: Identifica el origen de los productos.
- Imagen: Proporciona referencias visuales para los productos.
Identificación de Atributos:
Para cada entidad, se definen los atributos que son necesarios para cumplir con los requerimientos:
| Entidad | Atributos | Justificación |
|---|---|---|
| Producto | id, art, cod, tit, desc, cat_id, prov_id, img_id |
El art es el código interno único. El cod es el código del proveedor. Los IDs foráneos conectan con otras entidades. |
| Categoría | id, name, unit |
El name identifica la categoría. El unit especifica la unidad de medida estándar. |
| Proveedor | id, cod, name |
El cod es el identificador único del proveedor. El name es su razón social. |
| Imagen | id, url_img, txt_alt |
La url_img es la referencia al archivo. El txt_alt mejora la accesibilidad. |
Identificación de Relaciones:
Se definen las relaciones entre entidades:
- Producto N:1 Categoría (muchos productos en una categoría)
- Producto N:1 Proveedor (muchos productos de un proveedor)
- Producto N:1 Imagen (muchos productos pueden compartir una imagen)
4.3 Fase 3: Normalización
La normalización es un proceso que elimina redundancias y anomalías en el diseño de la base de datos. Se aplican reglas de normalización progresivas hasta alcanzar la tercera forma normal (3NF).
Primera Forma Normal (1NF):
La 1NF requiere que todos los atributos contengan valores atómicos (indivisibles) y que no haya grupos repetitivos. En nuestro modelo, cada atributo es atómico. Por ejemplo, en lugar de almacenar múltiples códigos de proveedor en un solo campo, cada producto tiene un único prov_id.
Segunda Forma Normal (2NF):
La 2NF requiere que la tabla esté en 1NF y que todos los atributos no clave dependan completamente de la clave primaria. En nuestro modelo, cada tabla tiene una clave primaria simple (id), y todos los atributos dependen de ella. Por ejemplo, en la tabla product, el atributo tit (título) depende del id del producto, no de ningún otro atributo.
Tercera Forma Normal (3NF):
La 3NF requiere que la tabla esté en 2NF y que no haya dependencias transitivas entre atributos no clave. En nuestro modelo, esto se logra separando las entidades. Por ejemplo, en lugar de almacenar el nombre de la categoría directamente en la tabla product, se almacena solo el cat_id, y el nombre se recupera de la tabla category. Esto evita que el nombre de la categoría dependa transitivamente del id del producto.
Ejemplo de Normalización:
Consideremos una tabla desnormalizada hipotética:
-- Tabla desnormalizada (ANTES)
CREATE TABLE product_desnormalizado (
id INT PRIMARY KEY,
art VARCHAR(50),
cod VARCHAR(50),
tit VARCHAR(150),
desc TEXT,
categoria_name VARCHAR(100), -- Redundancia: nombre de categoría repetido
categoria_unit VARCHAR(50), -- Redundancia: unidad de medida repetida
proveedor_cod VARCHAR(50), -- Redundancia: código de proveedor repetido
proveedor_name VARCHAR(100) -- Redundancia: nombre de proveedor repetido
);
Esta tabla tiene problemas:
- Anomalía de Inserción: No se puede insertar una categoría sin un producto.
- Anomalía de Actualización: Si el nombre de una categoría cambia, hay que actualizar múltiples filas.
- Anomalía de Eliminación: Si se elimina el único producto de una categoría, se pierde la información de la categoría.
Al normalizar a 3NF, se crean tablas separadas:
-- Tablas normalizadas (DESPUÉS)
CREATE TABLE category (
id INT PRIMARY KEY,
name VARCHAR(100),
unit VARCHAR(50)
);
CREATE TABLE prov (
id INT PRIMARY KEY,
cod VARCHAR(50),
name VARCHAR(100)
);
CREATE TABLE product (
id INT PRIMARY KEY,
art VARCHAR(50),
cod VARCHAR(50),
tit VARCHAR(150),
desc TEXT,
cat_id INT REFERENCES category(id),
prov_id INT REFERENCES prov(id)
);
Ahora:
- Inserción: Se puede insertar una categoría sin productos.
- Actualización: Cambiar el nombre de una categoría requiere una única actualización.
- Eliminación: Eliminar un producto no afecta la información de la categoría.
4.4 Fase 4: Diseño Físico
En esta fase, el modelo lógico normalizado se traduce a un esquema físico específico para MySQL, considerando tipos de datos, restricciones, índices y optimizaciones.
Selección de Tipos de Datos:
Para cada atributo, se selecciona el tipo de dato más apropiado:
| Atributo | Tipo de Dato | Justificación |
|---|---|---|
id |
INT AUTO_INCREMENT |
Identificador único autoincrementable. |
art, cod |
VARCHAR(50) |
Códigos alfanuméricos de longitud variable. |
tit |
VARCHAR(150) |
Título corto con longitud limitada. |
desc |
TEXT |
Descripción larga que puede exceder 255 caracteres. |
name |
VARCHAR(100) |
Nombre de categoría o proveedor. |
unit |
VARCHAR(50) |
Unidad de medida. |
url_img |
VARCHAR(255) |
URL de la imagen. |
txt_alt |
VARCHAR(255) |
Texto alternativo. |
Definición de Restricciones:
Se definen restricciones para garantizar la integridad de los datos:
- PRIMARY KEY: Cada tabla tiene una clave primaria (
id) que identifica unívocamente cada registro. - UNIQUE: Los campos
art(enproduct),name(encategory) ycod(enprov) son únicos para prevenir duplicados. - NOT NULL: Los campos obligatorios se marcan como
NOT NULL. - FOREIGN KEY: Las referencias entre tablas se definen con claves foráneas (
cat_id,prov_id,img_id). - ON DELETE SET NULL: Si una entidad padre es eliminada, las referencias en las entidades hijas se establecen como
NULL, preservando los registros.
Creación de Índices:
Se crean índices para optimizar las búsquedas:
- INDEX idx_art: Acelera las búsquedas por código de artículo.
- INDEX idx_cod: Acelera las búsquedas por código de proveedor.
- INDEX idx_cat_id: Acelera las búsquedas de productos por categoría.
- INDEX idx_prov_id: Acelera las búsquedas de productos por proveedor.
4.5 Fase 5: Validación y Optimización
En esta fase final, se valida el diseño contra los requerimientos y se realizan optimizaciones.
Validación:
- ¿Puede el sistema gestionar la importación masiva de productos? Sí, la estructura permite la creación automática de categorías y proveedores.
- ¿Se pueden prevenir duplicados? Sí, los índices únicos en
artycodlo aseguran. - ¿Se preserva la integridad de datos cuando se eliminan entidades? Sí, las restricciones
ON DELETE SET NULLlo garantizan. - ¿Es escalable el diseño? Sí, se pueden agregar nuevas entidades sin afectar la estructura existente.
Optimizaciones:
- Índices Compuestos: Si las búsquedas frecuentes combinan múltiples campos (p. ej.,
cat_idyprov_id), se puede crear un índice compuesto. - Particionamiento: Si la tabla
productcrece significativamente, se puede particionar por rango deido porcat_id. - Desnormalización Selectiva: En casos donde las búsquedas son muy frecuentes y el rendimiento es crítico, se puede desnormalizar selectivamente (p. ej., almacenar el nombre de la categoría en
productpara evitar JOINs).
5. Estructura de Datos
La estructura de datos define cómo se organizan y almacenan los datos en el sistema, considerando tanto la persistencia en la base de datos como la representación en memoria y en las comunicaciones entre cliente y servidor.
5.1 Consideraciones Generales
Al diseñar la estructura de datos, se consideran los siguientes principios:
-
Normalización: La base de datos sigue la tercera forma normal (3NF) para minimizar la redundancia de datos y garantizar la integridad referencial. Cada tabla representa una entidad distinta, y las relaciones se establecen mediante claves foráneas.
-
Escalabilidad: La estructura permite que el sistema crezca sin requerir cambios fundamentales. Por ejemplo, si en el futuro se necesita rastrear múltiples imágenes por producto, la relación puede adaptarse sin afectar la estructura existente.
-
Consistencia: Las claves foráneas con restricciones
ON DELETE SET NULLaseguran que la eliminación de una entidad padre no elimine automáticamente los registros dependientes, preservando la integridad de los datos históricos. -
Flexibilidad en la Importación: La estructura permite la creación automática de categorías y proveedores durante la importación de productos, sin requerir validación previa de estas entidades.
-
Prevención de Duplicados: Los campos
art(código de artículo) ycod(código de proveedor) pueden ser únicos o tener índices para facilitar búsquedas rápidas y prevenir duplicados.
5.2 Proceso de Derivación de la Estructura de Datos
La estructura de datos operativa se deriva del análisis del dominio del negocio mediante el siguiente proceso:
Paso 1: Identificación de Entidades
A partir del análisis de requerimientos, se identifican las entidades principales del dominio: Producto, Categoría, Proveedor e Imagen.
Paso 2: Definición de Atributos
Para cada entidad, se definen los atributos necesarios para satisfacer los casos de uso. Por ejemplo, el Producto requiere art y cod para permitir búsquedas y prevención de duplicados.
Paso 3: Establecimiento de Relaciones
Se definen las relaciones entre entidades basándose en las reglas de negocio. La relación N:1 entre Producto y Categoría refleja que cada producto tiene una única clasificación.
Paso 4: Normalización
La estructura se normaliza para eliminar redundancias. Por ejemplo, en lugar de almacenar el nombre de la categoría en cada registro de producto, se almacena solo el cat_id, y la categoría se recupera mediante una consulta JOIN.
Paso 5: Implementación en MySQL
La estructura conceptual se traduce a SQL, creando tablas con tipos de datos apropiados, claves primarias y foráneas.
5.3 Estructura de Datos Operativa
La estructura de datos operativa se representa en múltiples niveles: la base de datos relacional, los objetos en memoria (Python) y el formato de intercambio (JSON).
5.3.1 Esquema SQL (Base de Datos)
CREATE TABLE category (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL UNIQUE,
unit VARCHAR(50) NOT NULL
);
CREATE TABLE prov (
id INT AUTO_INCREMENT PRIMARY KEY,
cod VARCHAR(50) NOT NULL UNIQUE,
name VARCHAR(100) NOT NULL
);
CREATE TABLE image (
id INT AUTO_INCREMENT PRIMARY KEY,
url_img VARCHAR(255) NOT NULL,
txt_alt VARCHAR(255)
);
CREATE TABLE product (
id INT AUTO_INCREMENT PRIMARY KEY,
art VARCHAR(50) NOT NULL UNIQUE,
cod VARCHAR(50) NOT NULL,
tit VARCHAR(150) NOT NULL,
desc TEXT NOT NULL,
cat_id INT,
prov_id INT,
img_id INT,
FOREIGN KEY (cat_id) REFERENCES category(id) ON DELETE SET NULL,
FOREIGN KEY (prov_id) REFERENCES prov(id) ON DELETE SET NULL,
FOREIGN KEY (img_id) REFERENCES image(id) ON DELETE SET NULL,
INDEX idx_art (art),
INDEX idx_cod (cod)
);
5.3.2 Representación en Objetos Python
En el backend, los datos se representan como instancias de clases que heredan de la clase Tabla. Cada clase mapea una tabla de la base de datos:
class Categoria(Tabla):
tabla = 'category'
conexion = conexion
campos = ('id', 'name', 'unit')
def __init__(self, *args, de_bbdd=False):
super().crear(args, de_bbdd)
class Proveedor(Tabla):
tabla = 'prov'
conexion = conexion
campos = ('id', 'cod', 'name')
def __init__(self, *args, de_bbdd=False):
super().crear(args, de_bbdd)
class Imagen(Tabla):
tabla = 'image'
conexion = conexion
campos = ('id', 'url_img', 'txt_alt')
def __init__(self, *args, de_bbdd=False):
super().crear(args, de_bbdd)
class Producto(Tabla):
tabla = 'product'
conexion = conexion
campos = ('id', 'art', 'cod', 'tit', 'desc', 'cat_id', 'prov_id', 'img_id')
def __init__(self, *args, de_bbdd=False):
super().crear(args, de_bbdd)
5.3.3 Representación en JSON (API REST)
Cuando los datos se transmiten entre el backend y el frontend a través de la API REST, se serializan en formato JSON. A continuación se muestran ejemplos de estructuras JSON para cada entidad:
Ejemplo de Categoría en JSON:
{
"id": 1,
"name": "Herramientas",
"unit": "unidades"
}
Ejemplo de Proveedor en JSON:
{
"id": 5,
"cod": "PROV-001",
"name": "Distribuidora Industrial S.A."
}
Ejemplo de Imagen en JSON:
{
"id": 12,
"url_img": "https://cdn.ejemplo.com/productos/martillo-001.jpg",
"txt_alt": "Martillo de goma con mango de madera"
}
Ejemplo de Producto en JSON (sin relaciones expandidas):
{
"id": 42,
"art": "ART-0042",
"cod": "PROV-001-MAR",
"tit": "Martillo de Goma 500g",
"desc": "Martillo con cabeza de goma y mango de madera, ideal para trabajos que requieren no marcar la superficie.",
"cat_id": 1,
"prov_id": 5,
"img_id": 12
}
Ejemplo de Producto en JSON (con relaciones expandidas):
En algunos casos, es útil expandir las relaciones para evitar múltiples peticiones al cliente. Esta estructura es más completa pero también más pesada:
{
"id": 42,
"art": "ART-0042",
"cod": "PROV-001-MAR",
"tit": "Martillo de Goma 500g",
"desc": "Martillo con cabeza de goma y mango de madera, ideal para trabajos que requieren no marcar la superficie.",
"categoria": {
"id": 1,
"name": "Herramientas",
"unit": "unidades"
},
"proveedor": {
"id": 5,
"cod": "PROV-001",
"name": "Distribuidora Industrial S.A."
},
"imagen": {
"id": 12,
"url_img": "https://cdn.ejemplo.com/productos/martillo-001.jpg",
"txt_alt": "Martillo de goma con mango de madera"
}
}
Ejemplo de Respuesta de Lista de Productos:
Cuando la API devuelve una lista de productos, típicamente usa la estructura sin relaciones expandidas para mantener el tamaño de la respuesta manejable:
[
{
"id": 42,
"art": "ART-0042",
"cod": "PROV-001-MAR",
"tit": "Martillo de Goma 500g",
"desc": "Martillo con cabeza de goma...",
"cat_id": 1,
"prov_id": 5,
"img_id": 12
},
{
"id": 43,
"art": "ART-0043",
"cod": "PROV-001-DES",
"tit": "Destornillador Phillips #2",
"desc": "Destornillador de precisión con mango ergonómico...",
"cat_id": 1,
"prov_id": 5,
"img_id": 13
}
]
Ejemplo de Estructura de Importación desde Excel:
Cuando se importan productos desde un archivo Excel, el sistema procesa los datos y genera una estructura interna (en Python) que se valida antes de insertarse en la base de datos:
# Estructura interna durante la importación
import_data = [
{
"art": "ART-0042",
"cod": "PROV-001-MAR",
"tit": "Martillo de Goma 500g",
"desc": "Martillo con cabeza de goma y mango de madera",
"categoria": "Herramientas",
"proveedor_cod": "PROV-001",
"proveedor_name": "Distribuidora Industrial S.A.",
"imagen_url": "https://cdn.ejemplo.com/productos/martillo-001.jpg",
"imagen_alt": "Martillo de goma con mango de madera",
"estado": "procesado", # o "duplicado", "error"
"mensaje": "Producto importado exitosamente"
}
]
Ejemplo de Respuesta de Resultado de Importación:
Al finalizar la importación, el sistema devuelve un resumen en JSON:
{
"exitoso": true,
"resumen": {
"total_filas": 150,
"importados": 145,
"duplicados": 4,
"errores": 1
},
"detalles": [
{
"fila": 2,
"estado": "importado",
"producto_id": 42,
"mensaje": "Producto creado exitosamente"
},
{
"fila": 15,
"estado": "duplicado",
"mensaje": "Producto con art='ART-0015' ya existe"
},
{
"fila": 87,
"estado": "error",
"mensaje": "Campo obligatorio 'desc' faltante"
}
]
}
6. Diseño de la Solución: Modelo de Datos y Arquitectura
Con las reglas de negocio definidas, se procede al diseño técnico de la solución.
6.1 Modelo de Datos Relacional
Se opta por una base de datos relacional (MySQL) para garantizar la integridad y estructura de los datos. El esquema se compone de cuatro tablas principales:
| Tabla | Campos Principales | Descripción |
|---|---|---|
product |
id, art, cod, tit, desc, cat_id (FK), prov_id (FK), img_id (FK) |
Entidad central que almacena la información de cada producto. |
category |
id, name, unit |
Agrupa los productos en clasificaciones lógicas. |
prov |
id, cod, name |
Almacena la información de los proveedores. |
image |
id, url_img, txt_alt |
Contiene las referencias a las imágenes de los productos. |
Las claves foráneas (FK) en la tabla product establecen relaciones N:1 con las otras tablas, asegurando que cada producto tenga una categoría, un proveedor y una imagen asociados.
6.2 Arquitectura del Backend (Flask)
El backend se estructura de forma modular para separar responsabilidades, facilitando el mantenimiento y la escalabilidad:
/punto-ferretero-back
|-- app.py # Punto de entrada de la aplicación Flask.
|-- componentes/
| |-- vistas_api.py # Define los endpoints de la API REST (GET, POST, PUT, DELETE).
| `-- vistas_web.py # Define las rutas para la interfaz web de administración.
|-- base_db/
| |-- conexion_db.py # Gestiona la conexión con la base de datos MySQL.
| `-- tabla_db.py # Clase base con métodos CRUD genéricos.
|-- modelos.py # Define las clases (Producto, Categoria, etc.) que mapean las tablas de la BD.
`-- requirements.txt # Lista de dependencias de Python.
Un componente clave de esta arquitectura es la clase Tabla en tabla_db.py. Esta clase abstracta implementa métodos genéricos para las operaciones CRUD, que luego son heredados por las clases de modelo específicas (Producto, Categoria, etc.). Esto reduce significativamente la duplicación de código.
7. Historias de Usuario Esenciales
Las historias de usuario traducen los requerimientos en funcionalidades desde la perspectiva del usuario final.
7.1 HU-Admin-01: Gestión de Catálogo
-
Como: Administrador del sistema,
-
Quiero: poder crear, ver, modificar y eliminar productos, categorías y proveedores a través de una interfaz web,
-
Para: mantener el catálogo de productos actualizado y organizado.
Criterios de Aceptación:
- Debe existir una sección en la interfaz web para cada entidad (Productos, Categorías, Proveedores).
- Cada sección debe mostrar una lista de los registros existentes.
- Debe haber formularios para crear nuevos registros y para modificar los existentes.
- Debe existir una opción para eliminar cada registro, con una confirmación previa.
7.2 HU-Admin-02: Importación Masiva de Productos
-
Como: Administrador del sistema,
-
Quiero: poder subir un archivo Excel para cargar o actualizar múltiples productos de una sola vez,
-
Para: ahorrar tiempo y reducir errores en comparación con la carga manual.
Criterios de Aceptación:
- La interfaz debe tener una opción para seleccionar y subir un archivo
.xlsxo.xls. - El sistema debe procesar el archivo y añadir solo los productos que no existan previamente.
- Si un producto en el archivo tiene una categoría o proveedor nuevo, estos deben ser creados automáticamente.
- Al finalizar, el sistema debe mostrar un resumen indicando cuántos productos se importaron, cuántos eran duplicados y si ocurrieron errores.
- La interfaz debe tener una opción para seleccionar y subir un archivo
8. Caso de Uso Detallado: Importar Productos desde Excel
Este caso de uso es crítico para la operatividad del sistema y demuestra la implementación de varias reglas de negocio.
| Caso de Uso | Importar Productos desde Excel |
| Actor Principal | Administrador |
| Descripción | Permite al Administrador realizar una carga masiva de productos en el sistema a partir de un archivo Excel. |
| Precondiciones | 1. El Administrador ha iniciado sesión en el sistema. 2. El Administrador tiene un archivo en formato .xlsx o .xls que contiene los datos de los productos. |
| Postcondiciones | 1. Los nuevos productos (no duplicados) del archivo han sido añadidos a la tabla product. 2. Las nuevas categorías y proveedores han sido añadidos a sus respectivas tablas. 3. El sistema presenta al Administrador un informe del resultado de la importación. |
Flujo Principal de Eventos:
- El Administrador navega a la página "Subir Productos".
- El sistema presenta un formulario de carga de archivos.
- El Administrador selecciona el archivo Excel y hace clic en "Subir".
- El sistema recibe el archivo y valida que la extensión sea permitida (
.xlsxo.xls). - El sistema abre el archivo y lee la cabecera para mapear las columnas (p. ej., "Desc" a
descripcion). - El sistema itera sobre cada fila del archivo a partir de la segunda:
a. Extrae los datos del producto de la fila.
b. Regla de Negocio (Prevención de Duplicados): Verifica si ya existe un producto con el mismo
artocod. Si existe, marca la fila como duplicada y continúa con la siguiente. c. Regla de Negocio (Creación Automática): Busca el proveedor por su código. Si no lo encuentra, crea un nuevo registro en la tablaprov. d. Regla de Negocio (Creación Automática): Busca la categoría por su nombre. Si no la encuentra, crea un nuevo registro en la tablacategory. e. Crea el nuevo registro de producto en la tablaproductcon los datos de la fila y los IDs de las entidades relacionadas. - El sistema finaliza la iteración y prepara un resumen.
- El sistema redirige al Administrador a una página de resultados, mostrando el número de productos importados, la lista de duplicados omitidos y los errores encontrados.
Flujos Alternativos:
- 4a. Extensión de archivo inválida: Si el archivo no tiene una extensión permitida, el sistema rechaza la carga y muestra un mensaje de error.
- 6a. Fila con datos obligatorios faltantes: Si una fila no contiene un campo obligatorio (p. ej.,
desc), el sistema ignora la fila, registra un error y continúa con la siguiente.
9. Conclusión
La construcción de esta aplicación demuestra un proceso de desarrollo metódico donde las decisiones de arquitectura y tecnología están directamente impulsadas por los requerimientos del negocio. La elección de Flask y MySQL proporciona una base robusta y escalable, mientras que la separación clara entre el backend y el frontend a través de una API REST asegura un sistema modular y fácil de mantener.
El análisis detallado de las reglas de negocio y su traducción a casos de uso e historias de usuario es fundamental para garantizar que el producto final no solo sea técnicamente sólido, sino que también resuelva eficazmente el problema para el cual fue concebido. Los próximos pasos lógicos incluirían la implementación de un sistema de autenticación de usuarios más granular y la expansión de la API para soportar funcionalidades adicionales como la gestión de inventario.