diff --git a/README.md b/README.md index 814cee5..c6df38e 100644 --- a/README.md +++ b/README.md @@ -1,88 +1,232 @@ -# Bazaar API Orders +# Bazaar Orders API -## Overview +[![Java Version](https://img.shields.io/badge/Java-21-orange?style=for-the-badge&logo=openjdk)](https://openjdk.org/) +[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-4.0.6-brightgreen?style=for-the-badge&logo=springboot)](https://spring.io/projects/spring-boot) +[![Docker](https://img.shields.io/badge/Docker-Enabled-blue?style=for-the-badge&logo=docker)](https://www.docker.com/) +[![PostgreSQL](https://img.shields.io/badge/Database-PostgreSQL%2015-blue?style=for-the-badge&logo=postgresql)](https://www.postgresql.org/) +[![Flyway](https://img.shields.io/badge/Migrations-Flyway-red?style=for-the-badge&logo=flyway)](https://flywaydb.org/) +[![RabbitMQ](https://img.shields.io/badge/Message--Queue-RabbitMQ-orange?style=for-the-badge&logo=rabbitmq)](https://www.rabbitmq.com/) +[![OpenTelemetry](https://img.shields.io/badge/Telemetry-OpenTelemetry-blueviolet?style=for-the-badge&logo=opentelemetry)](https://opentelemetry.io/) -This module handles ... +The **Bazaar Orders API** is a Spring Boot microservice responsible for orchestrating checkout transactions, processing secure payments, managing order life cycles, tracking delivery statuses, and handling product/seller review systems within the Bazaar ecosystem. --- -## Environment Variables +## Table of Contents +1. [Core Features](#core-features) +2. [System Architecture](#system-architecture) +3. [Technology Stack](#technology-stack) +4. [Database Schema](#database-schema) +5. [Environment Configuration](#environment-configuration) +6. [Getting Started](#getting-started) + - [Prerequisites](#prerequisites) + - [Running with Docker Compose (Recommended)](#running-with-docker-compose-recommended) + - [Running Locally for Development](#running-locally-for-development) + - [Running Tests](#running-tests) + - [Stress / Load Testing (k6)](#stress--load-testing-k6) +7. [API Reference](#api-reference) +8. [Background & Scheduled Jobs](#background--scheduled-jobs) -Create a `.env` file based on [.env.example](/.env.example). +--- + +## Core Features + +- **Checkout & Multi-Seller Order Orchestration**: + - Groups items in the checkout request by seller and automatically creates separate orders for each. + - Consolidates orders under a single `OrderPayment` entity with a unique external reference. + - Integrates with **Mercado Pago API** to generate unified payment preferences and transaction flow. +- **Order Lifecycle Management**: + - Provides paginated purchase records for buyers and sales records for sellers. + - Enforces strict state transitions when updating order statuses (e.g., pending, paid, shipped, delivered, cancelled). + - Tracks detailed order status transitions via a history ledger. +- **Unified Review & Feedback System**: + - Allows customers to submit rating and written reviews for both overall orders (evaluating sellers) and individual order items (evaluating products). + - Computes and exposes real-time seller reputations (average rating, total counts). +- **Asynchronous Communication**: + - Leverages **RabbitMQ** to publish events and handle messaging tasks, such as stock notifications or inter-service communications. +- **Observability & Analytics**: + - Exposes comprehensive dashboard metrics for administrators: transaction volume, status counts, daily metrics, and category-specific order analytics. + - Monitored using an integrated OpenTelemetry agent for tracing and Prometheus/Grafana metric exports. + +--- + +## System Architecture + +The Orders API operates behind a routing **API Gateway**, trusting it to perform authentication checks and inject downstream headers: + +```mermaid +graph TD + Client([Client / App Mobile]) --> |HTTP Requests| Gateway[API Gateway] + Gateway -->|Forwards with X-User-Id & X-User-Role headers| OrdersService[Orders Microservice] + + subgraph Orders Service Internals + OrdersService --> |Reads/Writes| PostgreSQL[(PostgreSQL Database)] + OrderPaymentCleanupScheduler[OrderPaymentCleanupScheduler] --> |Purges expired/failed checkouts| PostgreSQL + RabbitMQProducer[RabbitMQProducer] --> |Publishes events| RabbitMQ[RabbitMQ Broker] + end + + OrdersService -->|Creates Payment Preferences| MercadoPago[Mercado Pago API] + MercadoPago -->|Webhook/IPN Notifications| OrdersService + OrdersService -->|HTTP REST Client| CatalogService[Catalog Microservice] + OrdersService -->|HTTP REST Client| UserService[User Microservice] + OrdersService -->|HTTP REST Client| CartService[Cart Microservice] + OrderPaymentCleanupScheduler -->|Restores Stock| CatalogService +``` + +> [!NOTE] +> Authorization is established by trusting the Gateway injected headers, specifically `X-User-Id` for the user context and `X-User-Role` for role permissions (`USER`, `ADMIN`). + +--- + +## Technology Stack + +- **Framework**: Spring Boot 4.0.6, Spring Security, Spring WebMVC, Spring Actuator, Spring Data JPA +- **Language**: Java 21 +- **Database**: PostgreSQL 15 +- **Database Migrations**: Flyway Database Migration +- **Caching**: Spring Cache with Caffeine Provider +- **Payment Broker**: Mercado Pago Java SDK (v2.9.2) +- **Messaging Service**: Spring AMQP / RabbitMQ +- **Monitoring & Observability**: OpenTelemetry JVM Agent, Slf4j, Spring Boot Actuator, Micrometer +- **Testing Tools**: JUnit 5, Spring WebTestClient, Testcontainers (PostgreSQL integration), Mockito + +--- + +## Database Schema + +Database migrations are managed automatically via Flyway scripts (`src/main/resources/db/migration`): + +1. **`order_payments`**: Manages the payments created with Mercado Pago. Stores unique external references, payment status, and timestamps. +2. **`orders`**: Links checkout records to their respective buyers (`user_id`), sellers (`seller_id`), delivery addresses, current statuses, and payment IDs. +3. **`order_items`**: Line items containing the product reference, price, quantity, and product category. +4. **`order_status_history`**: Holds status transition trails for auditing order lifecycles. +5. **`order_reviews`**: Captures buyer ratings (1 to 5) and feedback directed towards the seller. +6. **`order_item_reviews`**: Captures buyer reviews for individual items/products bought in an order, enforced by a unique buyer-to-item constraint. + +--- + +## Environment Configuration + +To configure the application, create a `.env` file in the root directory based on the [.env.example](.env.example) template: ```bash cp .env.example .env ``` +### Required Configuration Properties + +| Variable | Description | Default / Example | +|---|---|---| +| **Server Settings** | | | +| `PORT` | Local port of the Spring Boot application | `8080` | +| `HOST` | Bind address of the service | `0.0.0.0` | +| `ENVIRONMENT` | Running environment mode (`local`, `production`, `stress`) | `local` | +| **Database** | | | +| `DATABASE_HOST` | Host address of the PostgreSQL database | `database-host` | +| `DATABASE_NAME` | Database name | `database-name` | +| `DATABASE_PORT` | Database port | `5432` | +| `DATABASE_USER` | PostgreSQL user | `postgres` | +| `DATABASE_PASSWORD` | PostgreSQL password | `your-secure-password` | +| `EXPOSE_PORT` | Docker host-mapped port for PostgreSQL | `9000` | +| **API Endpoints** | | | +| `API_USER_URL` | Base URL routing for User microservice | `http://localhost:8080` | +| `API_CATALOG_URL`| Base URL routing for Catalog microservice | `http://localhost:8081` | +| `API_CART_URL` | Base URL routing for Cart microservice | `http://localhost:8082` | +| **Mercado Pago** | | | +| `MP_API_KEY` | Mercado Pago API Integration Credentials | *(From Mercado Pago Console)* | +| `MP_WEBHOOK_URL` | Public webhook callback URL (HTTPS required) | `https://your-domain.ngrok-free.app` | +| `SUCCESS_BACK_URL`| Redirect URL after a successful transaction | `https://bazaar.com/checkout/success`| +| `FAILURE_BACK_URL`| Redirect URL after a failed transaction | `https://bazaar.com/checkout/failure`| +| `PENDING_BACK_URL`| Redirect URL when payment is pending | `https://bazaar.com/checkout/pending`| +| **Ngrok Config** | | | +| `NGROK_AUTHTOKEN` | Auth token for tunneling webhook notifications locally | *(Optional)* | +| **RabbitMQ** | | | +| `RABBITMQ_ADDRESSES`| Endpoint addresses for RabbitMQ broker | `amqp://guest:guest@localhost:5672/` | +| **Telemetry (Grafana)**| | | +| `OTEL_SERVICE_NAME` | Service label reported in OpenTelemetry traces | `orders-service` | +| `OTEL_EXPORTER_OTLP_PROTOCOL`| Protocol for exporting OpenTelemetry records | `http/protobuf` | +| `OTEL_EXPORTER_OTLP_ENDPOINT`| Telemetry collector server address | `http://otel-collector:4317` | +| `OTEL_EXPORTER_OTLP_HEADERS` | Header properties injected into OTEL requests | *(Optional)* | + --- -## Running the Project +## Getting Started -1. **Clone the repository** - ```bash - git clone https://github.com/Baza-ar/api-orders.git api-orders - cd api-orders - ``` -2. **Configure the environment variables** Create a `.env` file based on [.env.example](/auth/.env.example): - * `PORT` - Backend running port. - * `HOST` - Backend running host address. - * `ENVIORMENT` - Running environment mode. - * `DATABASE_HOST` - Database running host address. - * `DATABASE_NAME` - Database name. - * `DATABASE_PORT` - Database running port. - * `DATABASE_USER` - Database user. - * `DATABASE_PASSWORD` - Database very hard to guess password. - * `EXPOSE_PORT` - Docker expose port for the database. - * `API_USER_URL` - API users URL. - * `API_CATALOG_URL` - API catalog URL - * `API_CART_URL` - API cart URL. - * `MP_API_KEY` - Mercado Pago's API key. - * `MP_WEBHOOK_URL` - Mercado Pago's webhook URL, it needs to be *https*. - * `FAILURE_BACK_URL` - Mercado Pago's failure back URL. - * `SUCCESS_BACK_URL` - Mercado Pago's success back URL. - * `PENDING_BACK_URL` - Mercado Pago's pending back URL. - * `NGROK_AUTHTOKEN` - NGROK's API key, this is optional. - * `RABBITMQ_ADDRESSES` - RabbitMQ's address. - * `OTEL_SERVICE_NAME` - Otel service name. - * `OTEL_EXPORTER_OTLP_PROTOCOL` - Otel used protocol. - * `OTEL_EXPORTER_OTLP_ENDPOINT` - Otel's endpoint address. - * `OTEL_EXPORTER_OTLP_HEADERS` - Otle's weird API key. -3. **Running the whole project** +### Prerequisites +- **Java Development Kit (JDK) 21** +- **Maven 3.9+** (or use the provided `mvnw` wrapper) +- **Docker & Docker Compose** + +### Running with Docker Compose (Recommended) + +To launch the microservice alongside PostgreSQL and RabbitMQ, execute the following: + +1. **Create the shared network** (if not already existing): + ```bash + docker network create bazaar-network + ``` +2. **Build and start the containers**: ```bash docker-compose up --build - ``` -> [!NOTE] -> You should only create the **Docker Network** once, check with. -> ```bash -> docker network ls -> ``` + ``` +3. **Stop the environment**: + ```bash + docker-compose down -v + ``` ---- +### Running Locally for Development + +For development, you can spin up the PostgreSQL database and RabbitMQ in Docker, and run the Spring Boot app locally: + +1. **Start PostgreSQL dependency**: + ```bash + docker-compose up postgres-orders -d + ``` +2. **Start RabbitMQ dependency**: + ```bash + docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management + ``` +3. **Compile and run the Spring Boot app**: + ```bash + ./mvnw spring-boot:run + ``` -## Stopping +### Running Tests +Run the test suite, which uses **Testcontainers** to instantiate isolated PostgreSQL containers: ```bash -# The flag -v is optional -docker-compose down -v +./mvnw clean test ``` +### Stress / Load Testing (k6) + +To execute stress testing using k6 performance configurations: + +1. **Configure the stress environment variables** in `.env`: + - Set `ENVIRONMENT` to `stress`. + - Set `RABBITMQ_ADDRESSES` to `amqp://guest:guest@rabbitmq:5672/`. +2. **Run the service in test mode**: + ```bash + docker compose -f docker-compose.test.yml up --build + ``` +3. **Shutdown the test infrastructure**: + ```bash + docker compose -f docker-compose.test.yml down -v + ``` + --- -## k6 Testing +## API Reference -In order to run the k6 tests, it is necessary to start the service in stress mode: +Interactive API documentation (Swagger UI) is available once the application runs at: +* **Swagger UI**: `http://localhost:8080/swagger-ui.html` +* **OpenAPI Definition JSON**: `http://localhost:8080/v3/api-docs` -1. **Configure the enviorment variables** Create a `.env` file based on [.env.example](/auth/.env.example): - * `ENVIORMENT` - Must be set to `stress`. - * `RABBITMQ_ADDRESSES` - Must be set to `amqp://guest:guest@rabbitmq:5672/`. -2. **Running the Service** - ```bash - docker compose -f docker-compose.test.yml up --build - ``` -3. **Stopping the Service** - ```bash - docker compose -f docker-compose.test.yml down -v - ``` +--- + +## Background & Scheduled Jobs + +The service runs an automated scheduler, the **`OrderPaymentCleanupScheduler`**, which periodically wakes up (every 10 minutes) to release inventory and clean up abandoned payment sessions: -> [!IMPORTANT] -> Please do not use production envs for k6 testing. If there is any issue, just ask. \ No newline at end of file +- **Abandoned Payments**: Detects `OrderPayment` transactions left in a `PENDING` state longer than the configured timeout (defaulting to 30 minutes). Releases/restores the product quantities back into stock via the Catalog API client and cleans up the transaction records. +- **Rejected Payments**: Scans for `REJECTED` payments. Restores the corresponding product stock and purges the records to prevent database bloating. \ No newline at end of file