Skip to content

This project delivers a robust and scalable RESTful API designed for comprehensive management of franchises, branches, and products.

License

Notifications You must be signed in to change notification settings

carrilloapps/franchises-api

πŸš€ Franquicias API

Latest Release πŸ§ͺ Tests Docker Image License: MIT Kotlin Spring Boot MongoDB Gradle Docker Follow me

This project delivers a robust and scalable RESTful API designed for comprehensive management of franchises, branches, and products. Developed with Spring Boot and Kotlin, it utilizes MongoDB for efficient and flexible data persistence. This API is ideal for businesses looking to streamline their franchise operations, offering functionalities for adding new franchises, managing branches, handling product inventory, and providing insightful data on stock levels.

Key Highlights:

  • πŸš€ Reactive Programming with Spring WebFlux for high-performance, non-blocking operations
  • πŸ“š Comprehensive API Documentation with enhanced Swagger/OpenAPI 3.0 integration
  • πŸ§ͺ 82% Code Coverage with 71 comprehensive tests across all layers
  • 🐳 Production-Ready Docker support with optimized multi-stage builds
  • ⚑ CI/CD Pipeline with automated testing, security scanning, and Docker image publishing
  • πŸ—οΈ Clean Architecture implementation following domain-driven design principles

πŸ› οΈ Technologies Used

  • Kotlin: A modern, concise, and safe programming language that runs on the JVM.
  • Spring Boot: A framework that simplifies the development of production-ready Spring applications.
  • MongoDB: A NoSQL document database designed for scalability and flexibility.
  • Gradle: A powerful build automation tool.
  • Docker: A platform for developing, shipping, and running applications in containers.
  • GitHub Actions: For continuous integration and continuous delivery (CI/CD).

πŸ“‚ Project Structure

franchises/
β”œβ”€β”€ .github/workflows/
β”‚   β”œβ”€β”€ ci.yml # GitHub Actions workflow for CI/CD
β”‚   └── docker-image.yml # GitHub Actions workflow for Docker image build and push
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ main/
β”‚   β”‚   β”œβ”€β”€ kotlin/app/carrillo/franchises/
β”‚   β”‚   β”‚   β”œβ”€β”€ FranchiseApplication.kt # Main application entry point
β”‚   β”‚   β”‚   β”œβ”€β”€ application/
β”‚   β”‚   β”‚   β”‚   └── FranchiseService.kt # Business logic services
β”‚   β”‚   β”‚   β”œβ”€β”€ config/
β”‚   β”‚   β”‚   β”‚   └── SwaggerConfig.kt # Configuration classes
β”‚   β”‚   β”‚   β”œβ”€β”€ domain/
β”‚   β”‚   β”‚   β”‚   └── Franchise.kt # Domain models (Franchise, Branch, Product)
β”‚   β”‚   β”‚   └── infrastructure/
β”‚   β”‚   β”‚       β”œβ”€β”€ FranchiseController.kt # REST API controllers
β”‚   β”‚   β”‚       β”œβ”€β”€ FranchiseRepository.kt # MongoDB repository
β”‚   β”‚   β”‚       └── HomeController.kt # Additional controllers
β”‚   β”‚   └── resources/
β”‚   β”‚       └── application.properties # Application configuration
β”‚   └── test/
β”‚       └── kotlin/app/carrillo/franchises/ # Unit and integration tests
β”œβ”€β”€ Dockerfile # Dockerfile for building the application image
β”œβ”€β”€ compose.yaml # Docker Compose file for local development setup
β”œβ”€β”€ build.gradle # Gradle build file
β”œβ”€β”€ gradlew # Gradle wrapper script (Linux/macOS)
β”œβ”€β”€ gradlew.bat # Gradle wrapper script (Windows)
β”œβ”€β”€ README.md # Project README file
β”œβ”€β”€ LICENSE # Project license file
β”œβ”€β”€ CONTRIBUTING.md # Guidelines for contributing to the project
└── CODE_OF_CONDUCT.md # Code of Conduct for contributors

πŸ“š Table of Contents

✨ Features

Core Functionality

  • Franchise Management: Complete CRUD operations for franchises with reactive programming support 🏒
  • Branch Operations: Add, update, and manage branches within franchises 🌳
  • Product Handling: Comprehensive product management with stock control and pricing πŸ“¦
  • Inventory Insights: Advanced queries for stock analysis and reporting πŸ“ˆ

Enhanced API Features

  • Reactive Programming: Built with Spring WebFlux for high-performance, non-blocking operations ⚑
  • Comprehensive API Documentation: Enhanced Swagger/OpenAPI 3.0 integration with detailed endpoint documentation πŸ“š
  • Error Handling: Robust error responses with proper HTTP status codes and descriptive messages πŸ›‘οΈ
  • CORS Support: Cross-origin resource sharing configuration for web applications 🌐

Dynamic Updates (Plus Features)

  • Franchise Updates: Update names, addresses, and descriptions ✍️
  • Branch Management: Modify branch names and details 🏷️
  • Product Operations: Update names, prices, and stock levels πŸ“
  • Real-time Inventory: Live stock tracking and management πŸ’°

Quality & Testing

  • 82% Code Coverage: Comprehensive test suite with 71 tests across all layers πŸ§ͺ
  • Reactive Testing: StepVerifier integration for testing reactive streams πŸ”¬
  • Multi-layer Testing: Unit, integration, and contract tests for all components βœ…

DevOps & Deployment

  • Docker Support: Production-ready containerization with multi-stage builds 🐳
  • CI/CD Pipeline: Automated testing, security scanning, and Docker image publishing βš™οΈ
  • GitHub Actions: Separate workflows for testing and Docker operations πŸš€
  • Security Scanning: Automated vulnerability detection in dependencies πŸ”’

βš™οΈ Prerequisites

Before you get started, ensure you have the following installed on your system:

  • Java Development Kit (JDK) 17 or higher: Download Link β˜•
  • Gradle: Typically bundled with Spring Boot projects, ensure it's accessible via your PATH or use ./gradlew. βš™οΈ
  • MongoDB: Follow the Installation Guide to set up your database. πŸƒ
  • Docker and Docker Compose (Optional, for containerized deployment): Download Link 🐳

πŸš€ Getting Started

Local Setup

  1. Clone the repository:

    git clone https://github.com/carrilloapps/franchises-api.git # Replace with actual repository URL
    cd franchises
  2. Build the project:

    ./gradlew build
  3. Run the application:

    ./gradlew bootRun

    The application will be accessible at http://localhost:3081. 🌐

Running with Docker

  1. Build the Docker image:

    ./gradlew bootBuildImage
  2. Run with Docker Compose: Utilize the provided compose.yaml for a seamless setup with MongoDB:

    docker compose up

    This command will launch both the MongoDB container and the Spring Boot application, making the application available at http://localhost:3081. 🐳

πŸ’Ύ Database Configuration

The application is configured to connect to a MongoDB instance. By default, it attempts to connect to mongodb://localhost:27017/franchisesdb. You can modify this configuration in src/main/resources/application.properties.

To quickly spin up a MongoDB instance using Docker:

docker run --name mongo-franchises -p 27017:27017 -d mongo

πŸ§ͺ Testing

Running Tests

To run all unit and integration tests, use the following Gradle command:

./gradlew test

This will execute all tests located in src/test/kotlin and provide a detailed report of the test results. βœ…

Test Coverage

Generate code coverage reports using JaCoCo:

./gradlew jacocoTestReport

Coverage reports are generated in:

  • HTML Report: build/reports/jacoco/test/html/index.html
  • XML Report: build/reports/jacoco/test/jacocoTestReport.xml

The project maintains a minimum coverage threshold of 80% with automatic verification:

./gradlew jacocoTestCoverageVerification

Current Test Coverage Status

βœ… Instruction Coverage: 82% (Target: 80%) - EXCEEDS REQUIREMENT
βœ… Branch Coverage: Enhanced coverage across all layers
βœ… Total Tests: 71 comprehensive tests (increased from 60)
βœ… All Tests Passing: Zero failures

Coverage by Package

  • Domain Layer (app.carrillo.franchises.domain): 100% coverage
  • Application Layer (app.carrillo.franchises.application): Enhanced coverage with comprehensive business logic tests
  • Infrastructure Layer (app.carrillo.franchises.infrastructure): Improved coverage including controller and repository tests
  • Configuration Layer (app.carrillo.franchises.config): Excluded from coverage reports (Swagger, Spring Boot configurations)

Test Structure

Our comprehensive testing suite focuses on the essential layers of the application:

πŸ—οΈ Domain Layer Tests (FranchiseTest.kt)

  • Entity Creation: Validates proper instantiation of Franchise, Branch, and Product entities
  • Data Integrity: Tests equality, hash codes, and data class functionality
  • Business Rules: Ensures domain constraints and validation rules
  • Edge Cases: Handles empty collections, null values, and boundary conditions

πŸ”§ Application Layer Tests (FranchiseServiceTest.kt)

  • Business Logic: Validates service layer operations and workflows
  • Transaction Management: Tests reactive transaction handling
  • Integration Points: Ensures proper interaction between layers
  • Exception Scenarios: Tests error handling and recovery mechanisms
  • Repository Integration: Tests service interaction with Spring Data MongoDB repository

βš™οΈ Configuration Tests (FranchiseApplicationTest.kt)

  • Spring Context: Validates application context loading
  • CORS Configuration: Tests cross-origin resource sharing setup
  • Bean Validation: Ensures proper dependency injection
  • Application Startup: Validates successful application initialization

Testing Technologies

  • JUnit 5: Modern testing framework with advanced features
  • Kotlin Test: Kotlin-specific testing utilities and assertions
  • Mockito: Comprehensive mocking framework for unit tests
  • Reactor Test: Specialized testing for reactive streams
  • StepVerifier: Reactive stream testing and verification
  • Spring Boot Test: Integration testing support for Spring applications
  • JaCoCo: Code coverage analysis and reporting

Test Execution Results

βœ… All tests pass successfully
βœ… Zero compilation errors
βœ… Comprehensive coverage across essential layers
βœ… Reactive programming patterns validated
βœ… Simplified architecture principles tested
βœ… Spring Data MongoDB integration validated

🌐 API Endpoints

All API endpoints are conveniently prefixed with /franchises. πŸ”—

πŸ“– Swagger UI

Once the application is up and running, you can explore and interact with the comprehensive API documentation via Swagger UI:

http://localhost:3081/swagger-ui.html

The enhanced Swagger documentation includes:

🎯 Enhanced Features

  • Comprehensive API Documentation: Detailed descriptions for all endpoints
  • Interactive Testing: Test all API endpoints directly from your browser
  • Request/Response Examples: Clear examples for all operations
  • Error Code Documentation: Complete HTTP status code explanations
  • Parameter Validation: Detailed parameter descriptions and constraints
  • Schema Definitions: Complete data model documentation

πŸ“Š Documentation Highlights

  • Test Coverage Information: Current 80% instruction coverage details
  • Quality Metrics: Information about 60+ comprehensive tests
  • Server Configuration: Both development and production server endpoints
  • Organized by Tags: Endpoints grouped by functionality (Franchise Management, Branch Operations, Product Management, Analytics)
  • Contact Information: Direct links to maintainer and repository

πŸ”§ API Categories

  1. Franchise Management: Core franchise CRUD operations
  2. Branch Operations: Branch management within franchises
  3. Product Management: Product inventory and pricing
  4. Analytics: Stock analysis and reporting endpoints

This interactive documentation makes it easy to understand, test, and integrate with the Franchises API. πŸ§ͺ

πŸš€ Deployment

This application can be easily deployed as a Docker container. The Dockerfile and GitHub Actions workflow (.github/workflows/docker-image.yml) are set up to automate the build and push of Docker images to the GitHub Container Registry. You can adapt this workflow for other container registries or deployment platforms.

For production deployments, consider using container orchestration tools like Kubernetes or Docker Swarm. 🚒

  • POST /

    • Description: Add a new franchise. βž•
    • Request Body: Franchise object (e.g., {"name": "Franchise A", "branches": []})
    • Response: Created Franchise object. βœ…
  • POST /{franchiseId}/branches

    • Description: Add a new branch to a franchise. 🌿
    • Request Body: Branch object (e.g., {"name": "Branch 1", "products": []})
    • Response: Updated Franchise object. βœ…
  • POST /{franchiseId}/branches/{branchName}/products

    • Description: Add a new product to a branch. πŸ“¦
    • Request Body: Product object (e.g., {"name": "Product X", "stock": 100})
    • Response: Updated Franchise object. βœ…
  • DELETE /{franchiseId}/branches/{branchName}/products/{productName}

    • Description: Delete a product from a branch. πŸ—‘οΈ
    • Response: Updated Franchise object. βœ…
  • PUT /{franchiseId}/branches/{branchName}/products/{productName}/stock?newStock={newStock}

    • Description: Modify the stock of a product. πŸ”„
    • Response: Updated Franchise object. βœ…
  • GET /{franchiseId}/products/most-stock

    • Description: Get the product with the most stock per branch for a specific franchise. πŸ“Š
    • Response: A list of maps, where each map contains a branch name and its highest stock product. βœ…
  • PUT /{franchiseId}/name?newName={newName} (Plus)

    • Description: Update the name of a franchise. ✍️
    • Response: Updated Franchise object. βœ…
  • PUT /{franchiseId}/address?newAddress={newAddress} (Plus)

    • Description: Update the address of a franchise. πŸ“
    • Response: Updated Franchise object. βœ…
  • PUT /{franchiseId}/description?newDescription={newDescription} (Plus)

    • Description: Update the description of a franchise. πŸ“œ
    • Response: Updated Franchise object. βœ…
  • GET /

    • Description: Get all franchises. πŸ“‹
    • Response: A list of Franchise objects. βœ…
  • GET /{id}

    • Description: Get a franchise by its ID. πŸ”
    • Response: A Franchise object. βœ…
  • PUT /{franchiseId}/branches/{oldBranchName}/name?newBranchName={newBranchName} (Plus)

    • Description: Update the name of a branch. 🏷️
    • Response: Updated Franchise object. βœ…
  • PUT /{franchiseId}/branches/{branchName}/products/{oldProductName}/name?newProductName={newProductName} (Plus)

    • Description: Update the name of a product. πŸ“
    • Response: Updated Franchise object. βœ…
  • PUT /{franchiseId}/branches/{branchName}/products/{productName}/price?newPrice={newPrice} (Plus)

    • Description: Update the price of a product. πŸ’°
    • Response: Updated Franchise object. βœ…

πŸ“Š Data Model

Franchise

data class Franchise(
    val id: String? = null,
    val name: String,
    val address: String? = null,
    val description: String? = null,
    val branches: List<Branch> = emptyList()
)

Branch

data class Branch(
    val name: String,
    val products: List<Product> = emptyList()
)

Product

data class Product(
    val name: String,
    var stock: Int,
    var price: Double? = null
)

🀝 Contribution Guidelines

We welcome contributions! Please refer to our Contribution Guidelines for detailed information on how to get involved, report bugs, suggest features, and submit code. Your contributions help make this project better! ✨

πŸ“œ Code of Conduct

To ensure a positive and inclusive environment, we adhere to a Code of Conduct. We expect all contributors and participants to follow these guidelines to foster a respectful and welcoming community. Please read it to understand expected behavior. πŸ’–

βš–οΈ License

This project is licensed under the MIT License. See the LICENSE file for more details. πŸ“„

πŸš€ CI/CD Pipeline

This project features a comprehensive CI/CD pipeline using GitHub Actions to ensure code quality, security, and automated deployment. πŸš€

Continuous Integration Workflow (.github/workflows/ci.yml)

Our CI pipeline automatically runs on:

  • Push events to master and develop branches
  • Pull requests targeting master and develop branches

Pipeline Stages

πŸ§ͺ Test Job
  • Environment: Ubuntu Latest with Java 17
  • Caching: Gradle dependencies cached for faster builds
  • Execution: Runs complete test suite with ./gradlew test
  • Coverage: Generates JaCoCo coverage reports
  • Validation: Ensures all tests pass before proceeding
πŸ—οΈ Build Job
  • Dependency: Runs only after successful test completion
  • Process: Compiles application using ./gradlew build
  • Artifacts: Validates build artifacts and dependencies
  • Quality Gate: Ensures zero compilation errors
πŸ”’ Security Scan Job
  • Dependency: Runs only after successful build completion
  • Tool: GitHub Security scanning for vulnerability detection
  • Scope: Analyzes dependencies and code for security issues
  • Reporting: Automatic security alerts and recommendations

Docker Image Automation

Additional GitHub Actions workflow for Docker image management:

  • Trigger: Automatically runs on new releases (published event). ➑️
  • Build Tool: Uses docker/build-push-action with Buildx for robust image building, including SBOM and provenance attestations. πŸ—οΈ
  • Registry: Pushes the built image to ghcr.io/${{ github.repository }}. Tags include the release version (e.g., v1.0.0 becomes 1.0.0). 🏷️
  • Authentication: Authenticates securely using GITHUB_TOKEN for access to the GitHub Container Registry. πŸ”‘

Quality Assurance

  • Automated Testing: Every code change triggers comprehensive test execution
  • Code Coverage: JaCoCo integration with 30% minimum coverage threshold
  • Security Scanning: Automated vulnerability detection and reporting
  • Build Validation: Ensures deployable artifacts before merge
  • Branch Protection: Quality gates prevent broken code from reaching main branches

Running from GitHub Container Registry Image

To run the application directly from the Docker image published to GitHub Container Registry, follow these steps:

  1. Ensure Docker is installed: Make sure you have Docker installed on your system. If not, you can download it from the official Docker website.

  2. Pull the Docker image: Replace YOUR_REPOSITORY with your GitHub username or organization and YOUR_IMAGE_NAME with the repository name (e.g., franchises-api). Replace TAG with the desired release version (e.g., 1.0.0).

    docker pull ghcr.io/YOUR_REPOSITORY/YOUR_IMAGE_NAME:TAG

    For example, to pull the v1.0.0 image of this project:

    docker pull ghcr.io/carrilloapps/franchises-api:1.0.0
  3. Run the Docker container: You can run the image, mapping the application's port (3081) to a port on your host machine. Also, ensure your MongoDB instance is accessible from the container.

    docker run -p 3081:3081 ghcr.io/YOUR_REPOSITORY/YOUR_IMAGE_NAME:TAG

    If your MongoDB is running on localhost and you are running Docker on Linux, you might need to use host.docker.internal or the host's IP address for the MongoDB connection string within the container, or link a MongoDB container.

    Example with MongoDB running in a separate container (using compose.yaml is recommended for this):

    docker run -p 3081:3081 --network host ghcr.io/carrilloapps/franchises-api:1.0.0

    (Note: --network host might not be available on all Docker environments, especially Docker Desktop on macOS/Windows, where host.docker.internal is preferred for host access.)

  4. Access the application: Once the container is running, the application will be accessible at http://localhost:3081.

About

This project delivers a robust and scalable RESTful API designed for comprehensive management of franchises, branches, and products.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages