Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
266 changes: 205 additions & 61 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.
- **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.
Loading