Skip to content

Repository files navigation

Microservicio de Precios y Promociones (Ejemplo SOA)

Este proyecto es un microservicio de ejemplo desarrollado en Python con Flask, diseñado para ilustrar la implementación de patrones de arquitectura orientada a servicios (SOA) en un contexto práctico de retail.

El servicio expone un único endpoint para calcular el precio final de un producto, aplicando reglas de negocio como descuentos por tipo de cliente y validación de cupones.

Patrones Arquitectónicos Demostrados

El código está estructurado para demostrar los siguientes principios de SOA:

  1. Canonical Schema (Esquema Canónico): El servicio no opera directamente con los identificadores de producto de los sistemas de origen (ej: P12345 del e-commerce o 789123 del POS). En su lugar, los transforma a un formato canónico (SKU-WEB-001, SKU-LEGACY-ABC) antes de procesarlos. Esto se simula en server.py con la función transformar_a_canonico.

  2. Logic Centralization (Centralización de la Lógica): Las reglas de negocio complejas o que cambian con frecuencia (como la validación de un cupón) no están codificadas directamente en el servicio principal. En su lugar, se delegan a un componente especializado (ReglasNegocioClient), que simula una llamada a un motor de reglas externo.

  3. Service Normalization (Normalización del Servicio): La clase PreciosPromocionesService actúa como una fachada unificada. Consolida la lógica de orquestación (obtener precio base, consultar reglas, aplicar descuentos) en una única interfaz cohesiva, independientemente de la complejidad de las dependencias subyacentes.

  4. Inyección de Dependencias: El PreciosPromocionesService no crea sus propias dependencias (como ReglasNegocioClient). En su lugar, las recibe en su constructor. Este desacoplamiento es clave para la mantenibilidad y, especialmente, para la capacidad de prueba, ya que permite "inyectar" versiones falsas (mocks) de las dependencias durante las pruebas unitarias.

Estructura del Proyecto

omniRetail-precio-service/
├── services/
│   ├── __init__.py
│   └── PreciosPromocionesService.py  # Lógica de negocio principal
├── tests/
│   ├── __init__.py
│   └── test_precios_promociones_service.py # Pruebas unitarias del servicio
├── .gitignore
├── README.md
├── requirements.txt                    # Dependencias del proyecto
├── server.py                           # Servidor Flask y endpoint API
└── venv/                               # Entorno virtual (ignorado por Git)

Requisitos

  • Python 3.8+
  • pip y venv

Instalación

  1. Clona el repositorio:

    git clone <URL_DEL_REPOSITORIO>
    cd omniRetail-precio-service
  2. Crea y activa un entorno virtual:

    # En macOS/Linux
    python3 -m venv venv
    source venv/bin/activate
    
    # En Windows
    python -m venv venv
    .\venv\Scripts\activate
  3. Instala las dependencias:

    pip install -r requirements.txt

Ejecución

Iniciar el Servicio

Para iniciar el servidor web de Flask, ejecuta el siguiente comando desde la raíz del proyecto:

python server.py

El servicio estará disponible en http://127.0.0.1:5000.

Ejecutar las Pruebas

Para verificar que la lógica del servicio funciona como se espera, puedes ejecutar las pruebas unitarias con pytest:

pytest -v

Verás una salida que confirma que todas las pruebas han pasado.

Uso de la API

El servicio expone un único endpoint para calcular precios.

  • Endpoint: POST /api/precios/calcular
  • Content-Type: application/json

Cuerpo de la Solicitud (Request Body)

Campo Tipo Obligatorio Descripción
id_producto String El identificador del producto (ej: "P12345").
cliente_tipo String El tipo de cliente (ej: "VIP", "Regular").
cupon String No El código del cupón de descuento a aplicar.

Ejemplos de uso con cURL

1. Cliente VIP con cupón válido:

curl -X POST http://127.0.0.1:5000/api/precios/calcular \
-H "Content-Type: application/json" \
-d '{
      "id_producto": "P12345",
      "cliente_tipo": "VIP",
      "cupon": "20OFFELEC"
    }'

Respuesta Esperada (descuento VIP del 5% + descuento del cupón del 20% sobre el precio base de 100):

{
  "mensaje": "Cálculo exitoso y reglas aplicadas.",
  "precio_final": 75.00,
  "sku_procesado": "SKU-WEB-001"
}

2. Producto no encontrado:

curl -X POST http://127.0.0.1:5000/api/precios/calcular \
-H "Content-Type: application/json" \
-d '{"id_producto": "ID_INEXISTENTE", "cliente_tipo": "Regular"}'

Respuesta Esperada:

{
  "error": "Producto con SKU canónico 'ID_INEXISTENTE' no encontrado."
}

About

micros

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages