← Volver al blog

Publicación

Racoonity ya entiende productos

Terminamos el primer catálogo dinámico de Racoonity: categorías, productos, permisos, eventos, metadata y contratos de interfaz trabajando como un solo sistema.

Por El equipo de Racoonity
5 min de lectura
#desarrollo#arquitectura#catálogo#metadata#racoonity

Durante las últimas semanas hemos hablado de cimientos, motores, permisos, contratos y nombres de mapaches con profesiones sospechosamente específicas.

Todo eso era necesario, pero todavía faltaba algo importante:

que Racoonity comenzara a hacer algo reconocible como producto.

Hoy alcanzamos ese punto.

Terminamos la segunda gran iteración del primer MVP: el catálogo dinámico de productos.

Y aunque “crear productos y categorías” puede sonar como una función bastante normal para un sistema comercial, detrás de esa pantalla aparentemente sencilla ya existe una parte importante de la arquitectura que queremos construir para Racoonity.

El primer dominio comercial del mapache

Racoonity ahora puede trabajar con dos conceptos fundamentales:

  • categorías;
  • productos.

Una categoría puede crearse, modificarse, archivarse y habilitarse nuevamente.

Un producto puede registrar información como:

  • nombre;
  • SKU;
  • código de barras;
  • descripción;
  • categoría;
  • precio de venta;
  • unidad;
  • estado.

También puede consultarse, buscarse, filtrarse, ordenarse, archivarse y volver a habilitarse.

El SKU es único dentro de cada empresa, los códigos de barras respetan sus propias reglas de unicidad y un producto solo puede relacionarse con categorías pertenecientes a la misma compañía.

Todo esto ocurre sin almacenar existencias dentro del producto.

Esa separación es deliberada: el catálogo describe qué es el producto. El inventario, en una iteración posterior, será responsable de responder cuánto existe y dónde está.

Archivar no significa borrar

En Racoonity, productos y categorías no desaparecen físicamente cuando dejan de utilizarse.

Se archivan.

Esto permite conservar referencias, historial y consistencia sin fingir que algo nunca existió.

Una categoría archivada puede seguir apareciendo como referencia dentro de un producto existente, pero no puede asignarse a productos nuevos ni utilizarse para volver a habilitar un producto mientras permanezca archivada.

Son reglas pequeñas, pero importantes. El objetivo no es solamente que el sistema acepte datos: debe proteger su significado.

Permisos reales, no botones escondidos

El catálogo ya trabaja con los roles definidos desde la iteración anterior.

Un administrador puede crear y modificar categorías y productos.

Los perfiles de caja y consulta pueden leer el catálogo activo, pero no ejecutar modificaciones ni acceder directamente a registros archivados.

Además, Racoonity evita revelar información entre empresas.

Para un usuario sin acceso, un registro inexistente, uno perteneciente a otra compañía y uno archivado que debe permanecer oculto producen la misma respuesta pública.

Esto evita que alguien pueda utilizar el sistema para descubrir indirectamente qué información existe fuera de su alcance.

Y algo especialmente importante:

ocultar una acción en la interfaz no reemplaza la autorización.

Aunque un botón no aparezca, Racoon Bouncer continúa verificando cada operación cuando alguien intenta ejecutarla directamente.

La interfaz orienta. Bouncer decide.

Productos que dejan huella

Las operaciones importantes sobre productos ahora generan eventos internos:

  • product.created;
  • product.updated;
  • product.archived.

Estos eventos se guardan en el outbox dentro de la misma transacción que modifica el producto.

Eso significa que no puede ocurrir esto:

El producto se guardó, pero olvidamos registrar el evento.

Ni esto:

Registramos que el producto nació, pero la creación realmente falló.

Producto, evento e idempotencia se confirman juntos o se revierten juntos.

Todavía no existe un sistema externo distribuyendo esos eventos. Eso llegará después. En esta iteración nos interesaba construir una base local, durable y confiable.

Repetir una operación no significa duplicarla

Las acciones de categorías y productos son idempotentes.

Cuando una solicitud se repite con la misma clave y el mismo contenido, Racoonity puede recuperar el resultado anterior sin ejecutar nuevamente la operación.

Cuando se reutiliza la misma clave con un contenido diferente, el sistema detecta el conflicto.

Esto es especialmente importante para evitar productos duplicados, eventos repetidos o estados inconsistentes cuando una aplicación reintenta una petición debido a problemas de red.

Metadata que ya sirve para algo

Hasta ahora, hablar de Metadata podía sonar bastante abstracto.

En esta iteración dejó de serlo.

Racoonity guarda definiciones que describen:

  • módulos;
  • modelos;
  • campos;
  • relaciones;
  • vistas;
  • acciones;
  • navegación.

La metadata inicial pertenece al sistema y se instala mediante migraciones. Todavía no puede ser editada por usuarios y todavía no existe Racoon Artifier como superficie de construcción.

Eso es intencional.

Primero necesitábamos comprobar que Racoonity pudiera consumir definiciones confiables antes de permitir que alguien comenzara a crearlas.

Racoon Atlas ya puede resolver el mapa

Racoon Atlas carga la metadata disponible y construye una representación de solo lectura.

A partir de ella puede resolver:

  • el modelo de categorías;
  • el modelo de productos;
  • sus campos;
  • sus relaciones;
  • sus vistas;
  • sus acciones;
  • su navegación.

Atlas no autoriza operaciones, no consulta productos y no modifica metadata.

Su trabajo es resolver definiciones.

La autorización sigue perteneciendo a Racoon Bouncer. Los datos comerciales siguen perteneciendo a Catalog. La presentación sigue siendo responsabilidad de Painter.

Mantener esas fronteras es una parte central de la arquitectura de Racoonity.

Painter compone, pero todavía no dibuja

Racoon Painter ya puede convertir las definiciones resueltas por Atlas en contratos de presentación.

Actualmente puede producir contratos para tres tipos de vista:

  • lista;
  • formulario;
  • detalle.

Estos contratos describen qué campos existen, su orden, su tipo, cuáles son obligatorios, qué relaciones poseen y qué acciones puede mostrar la interfaz para el usuario actual.

Painter todavía no genera React, HTML ni ventanas de escritorio.

No dibuja una pantalla.

Describe cómo una pantalla puede ser construida.

Por ejemplo, el contrato de un producto puede indicar que category_id representa una relación hacia el modelo de categorías y que debería mostrarse mediante un selector de relación.

Más adelante, una interfaz podrá consumir esa descripción y decidir cómo representarla visualmente.

La primera demostración de la idea dinámica

La cadena que ya funciona es esta:

Metadata persistida
→ Racoon Atlas resuelve
→ los permisos filtran
→ Racoon Painter compone
→ la aplicación recibe un contrato de presentación