Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 

Repository files navigation

📱 Boutika - Enterprise Retail Management System

A sophisticated backend SaaS platform for managing multi-store mobile retail operations in real-time, combining advanced inventory management, transactional integrity, and enterprise-grade security.

Java Spring Boot PostgreSQL Maven Docker


🎯 Project Overview

MobileStore is an enterprise-level REST API backend designed for managing multi-store mobile phone retail operations. It provides:

  • 🏪 Multi-store Management: Centralized control across distributed retail locations
  • 📦 Intelligent Inventory Management: Real-time stock tracking with historical analytics
  • 💼 Role-Based Access Control (RBAC): Granular security with employer and employee hierarchies
  • 🛒 Order Management System: Complete order lifecycle from creation to fulfillment
  • 💰 Financial Tracking: Sales analytics and spending management
  • 🔐 Enterprise Security: JWT-based authentication with transactional integrity

This system is engineered for high-traffic retail environments requiring reliability, scalability, and rigorous data consistency.


🏗️ Technical Architecture

Layered Architecture Pattern

┌─────────────────────────────────────┐
│      REST API Controllers Layer      │  <- HTTP Request Handling
├─────────────────────────────────────┤
│      Service Layer (Business Logic)  │  <- Orchestration & Validation
├─────────────────────────────────────┤
│      Repository Layer (Data Access)  │  <- JPA/JDBC Abstraction
├─────────────────────────────────────┤
│      Database Layer (PostgreSQL)     │  <- Persistent Storage
└─────────────────────────────────────┘

Core Components

Component Purpose Highlights
Controllers Request routing & HTTP response handling Clean request/response mapping with ResponseBuilder
Services Business logic orchestration @Transactional boundaries for data consistency
Repositories Data persistence layer Spring Data JPA with custom query methods
DTOs Data transfer objects Decoupling API contracts from domain models
Security Authentication & Authorization JWT tokens with SecurityValidator
Exceptions Global error handling Custom exception hierarchy with meaningful messages

⚡ Key Technical Features

1. Transactional Integrity & ACID Compliance

✓ @Transactional(rollbackOn = Exception.class) annotations
✓ Multi-entity operations atomically processed
✓ OrderContent service: Ensures order/stock synchronization

2. Role-Based Access Control (RBAC)

✓ Employer → Store Owner privileges
✓ Employee → Store Manager/Salesperson roles
✓ @PreAuthorize("hasRole('EMPLOYER')") method-level security
✓ SecurityValidator: Custom access validation per entity

3. Advanced Inventory Management

  • Stock Tracking: Real-time quantity updates with historical snapshots
  • Restock Operations: Automated stock replenishment logic
  • Sales Analytics: Product-level sales statistics over time periods
  • Bulk Operations: Efficient multi-product updates via Map-based processing

4. Global Exception Handling

Custom exception hierarchy for semantic error differentiation:

  • ElementNotFoundException - Resource not found
  • CreationFailedException - Creation operations
  • AccessDeniedException - Authorization failures
  • NotAuthenticatedException - Missing credentials

5. Production-Ready Security

  • JWT Authentication: JJWT library with 24-hour token expiration
  • Password Encoding: Spring Security PasswordEncoder integration
  • OAuth2 Support: OAuth2 client configuration
  • Stateless Security: Fully stateless API design

6. Sophisticated Query Patterns

// Date-range filtering with relationship traversal
findAllByDateIsBetweenAndPreviousStockIsNotNullAndProductIdIn()

// Relationship validation across stores
existsAllByIdInAndStoreId()

// User context-aware queries
findStoresByEmployerIdOrEmployeesId()

💎 Code Highlights: Architecture Excellence

Clean Code & SOLID Principles

1️⃣ Dependency Injection & Single Responsibility

@Service
public class OrderContentService implements IOrderContent {
    private final OrderRepository orderRepository;
    private final ProductRepository productRepository;
    private final StockService stockService;
    private final SecurityValidator securityValidator;

    // Constructor injection - explicit dependencies
    public OrderContentService(
        OrderService orderService,
        SecurityValidator securityValidator,
        OrderRepository orderRepository,
        ProductRepository productRepository,
        OrderContentRepository orderContentRepository,
        ProductService productService,
        CategoryRepository categoryRepository,
        StockService stockService
    ) {
        // Clean initialization
    }

Why this is excellent:

  • ✅ No service locators or static dependencies
  • ✅ Full testability via mock injection
  • ✅ Clear contract through constructor signature
  • ✅ Respects Single Responsibility Principle (SRP)

2️⃣ DTO Pattern for API Decoupling

// Domain Model (Internal)
@Data
public class Order {
    private UUID id;
    private Store store;
    private Person maker;
    private OrderStatus status;
    private Map<Product, OrderContent> products;
}

// DTO Layer (API Contract)
@Data
public class OrderDto {
    private UUID orderId;
    private String storeName;
    private String makerUsername;
    private OrderStatus status;
    
    public void fromOrder(Order order) {
        this.orderId = order.getId();
        this.storeName = order.getStore().getName();
        // Prevents exposing internal relationships
    }
}

Why this is excellent:

  • Loose Coupling: API clients unaffected by domain changes
  • Security: Sensitive fields never exposed
  • Clean Contracts: Explicit API boundaries
  • ✅ Respects Interface Segregation Principle (ISP)

3️⃣ Method-Level Security with Atomic Transactions

@Service
public class OrderService implements IOrder {
    
    @Override
    @PreAuthorize("(@securityValidator.hasRole('EMPLOYER') || @securityValidator.hasRole('EMPLOYEE'))")
    @Transactional(rollbackOn = Exception.class)
    public Order create(Order order, UUID storeId) 
        throws CreationFailedException, NotAuthenticatedException, AccessDeniedException {
        
        // 1. Security validation
        secCheck.validateStoreAccess(storeId);
        
        // 2. Context extraction
        Authentication auth = secCheck.getAuthentication();
        Person person = secCheck.findUserFromAuthentication(auth, Person.class);
        
        // 3. Business logic with atomicity guarantee
        Store store = storeRepository.getReferenceById(storeId);
        order.setStore(store);
        order.setMaker(person);
        order.setStatus(OrderStatus.CREATED);
        
        return orderRepository.save(order);
    }
}

Why this is excellent:

  • Declarative Security: AOP-based authorization
  • Transactional Safety: Complete operation atomicity
  • Separation of Concerns: Security ≠ Business Logic
  • ✅ Respects Open/Closed Principle (OCP) - extensible security rules

4️⃣ Sophisticated State Management with Streams

@Transactional
public List<Stock> sellManyProduct(Map<UUID, Double> sellProducts) {
    List<UUID> productIds = sellProducts.keySet().stream().toList();
    List<Product> products = productRepository.findAllById(productIds);
    
    // Functional mapping: O(1) lookups for validation
    Map<UUID, Stock> productsStocks = products.stream()
        .collect(Collectors.toMap(Product::getId, Product::getStock));
    
    List<Stock> updatedStocks = new ArrayList<>(productsStocks.size());
    
    // Validation + Update in single pass
    sellProducts.forEach((productId, quantity) -> {
        Stock stock = productsStocks.get(productId);
        
        if ((stock.getTotalSell() + quantity) > stock.getBaseStock()) {
            throw new OperationFailedException("product out of stock");
        }
        
        stock.setTotalSell(stock.getTotalSell() + quantity);
        updatedStocks.add(stock);
    });
    
    return stockRepository.saveAll(updatedStocks);
}

Why this is excellent:

  • Functional Programming: Immutable stream operations
  • Performance: Single database query, O(1) validation lookups
  • Bulk Operations: Batch saves reduce DB round-trips
  • ✅ Respects Dependency Inversion Principle (DIP)

5️⃣ Polymorphic Security Context Handling

@Transactional
public Order update(Order order, UUID id) 
    throws UpdateFailedException, ElementNotFoundException, AccessDeniedException {
    
    Authentication auth = secCheck.getAuthentication();
    
    // Runtime polymorphism: determine user type dynamically
    Class<? extends Person> userType = (auth.getAuthorities()
        .stream()
        .anyMatch(a -> Objects.requireNonNull(a.getAuthority()).contains("EMPLOYER")))
        ? Employer.class
        : Employee.class;
    
    Person user = secCheck.findUserFromAuthentication(auth, userType);
    Order existingOrder = orderRepository.findById(id)
        .orElseThrow(() -> new ElementNotFoundException("Order not found"));
    
    // Authorization: only original maker can update
    if (!existingOrder.getMaker().equals(user)) {
        throw new AccessDeniedException("You're not the order maker");
    }
    
    // State machine: CREATED → VALIDATED → UPDATED
    OrderStatus newStatus = switch (order.getStatus()) {
        case CREATED -> OrderStatus.VALIDATED;
        case VALIDATED -> OrderStatus.UPDATED;
        default -> null;
    };
    
    order.setStatus(newStatus);
    return orderRepository.save(order);
}

Why this is excellent:

  • Polymorphism: Type-safe user discrimination
  • State Machines: Enforced valid transitions
  • Authorization Semantics: Business rule enforcement
  • Modern Java: Switch expressions (Java 21)
  • ✅ Respects Liskov Substitution Principle (LSP)

🛠️ Tech Stack

Core Framework

  • Java 21: Latest LTS with modern language features (records, pattern matching, sealed classes)
  • Spring Boot 4.0.0: Enterprise application development
  • Spring Security: Authentication & authorization framework
  • Spring Data JPA: Object-relational mapping abstraction

Security & Cryptography

  • JJWT (JSON Web Tokens): JWT generation and validation
  • Spring Security OAuth2 Client: OAuth2 authentication support
  • BCrypt Password Encoder: Secure password hashing

Data Access & Persistence

  • PostgreSQL: Enterprise relational database
  • Spring Data JDBC: Alternative lightweight persistence
  • Liquibase: Database schema versioning and migration
  • Hibernate ORM: JPA implementation

Build & DevOps

  • Maven 3.9.6: Dependency management and build automation
  • Docker: Containerization (Alpine-based)
  • Eclipse Temurin JDK 21: Official OpenJDK distribution

Testing & Quality

  • Spring Boot Test: Integration testing framework
  • AssertJ: Fluent assertion library
  • JUnit 5: Modern testing framework

Development Tools

  • Lombok: Boilerplate reduction (@Data, @Slf4j)
  • Jackson: JSON serialization/deserialization
  • SLF4J + Logback: Structured logging

📦 Installation & Usage

Prerequisites

  • Java 21+ (JDK)
  • Maven 3.9.0+
  • PostgreSQL 14+
  • Docker (optional)

Step 1: Clone Repository

git clone https://github.com/paka-ops/MobileStore.git
cd MobileStore

Step 2: Configure Environment

Create application.properties or application-prod.properties:

# Database Configuration
spring.datasource.url=jdbc:postgresql://localhost:5432/mobilestore
spring.datasource.username=your_db_user
spring.datasource.password=your_db_password

# JWT Security
app.jwt.key=your_base64_encoded_secret_key

# Server Port
server.port=8080

# Liquibase Migrations
spring.liquibase.change-log=classpath:db/changelog/db.changelog-master.xml

Step 3: Build Project

# Using Maven Wrapper (recommended)
./mvnw clean package

# Or standard Maven
mvn clean package -DskipTests

Step 4: Run Application

# Run with Maven
./mvnw spring-boot:run

# Or run compiled JAR
java -Dspring.profiles.active=prod -jar target/eGestion-0.0.1-SNAPSHOT.jar

Step 5: Docker Deployment (Optional)

# Build Docker image
docker build -t mobilestore:latest .

# Run container
docker run -d \
  --name mobilestore \
  -p 8080:8080 \
  -e SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/mobilestore \
  -e APP_JWT_KEY=your_secret_key \
  mobilestore:latest

🚀 API Endpoints Overview

Authentication & Authorization

POST   /api/v1/employers          - Create employer account
POST   /api/v1/auth/login         - JWT token generation

Store Management

GET    /api/v1/stores             - List all stores
POST   /api/v1/stores             - Create store
PATCH  /api/v1/stores/{id}        - Update store
DELETE /api/v1/stores/{id}        - Delete store

Product & Inventory

GET    /api/v1/products?storeId=uuid           - List products by store
POST   /api/v1/products?categoryId=uuid        - Add product
PATCH  /api/v1/products/{id}?quantity=50      - Restock product
GET    /api/v1/products/{id}/stats            - Product sales analytics

Order Management

POST   /api/v1/orders?storeId=uuid                            - Create order
GET    /api/v1/orders?storeId=uuid&startDate=2026-01-01     - List orders (filtered)
PATCH  /api/v1/orders/{id}                                   - Update order status
DELETE /api/v1/orders/{id}                                   - Cancel order

Employee Management

GET    /api/v1/employee?storeId=uuid    - List store employees
POST   /api/v1/employee?storeId=uuid    - Hire employee
PATCH  /api/v1/employee/{id}            - Update employee

🔒 Security Architecture

JWT Token Flow

┌─────────────┐
│   Client    │
└──────┬──────┘
       │ 1. POST /login (credentials)
       ▼
┌─────────────────────────────────┐
│  JwtService.jwtGenerator()      │
│  - Generate HS256 signed token  │
│  - 24-hour expiration           │
│  - Username in subject claim    │
└──────┬──────────────────────────┘
       │ 2. Return JWT token
       ▼
┌─────────────┐
│   Client    │ 3. Include token in Authorization header
└──────┬──────┘
       │
       ▼
┌─────────────────────────────────┐
│  SecurityValidator              │
│  - Verify token signature       │
│  - Extract username             │
│  - Load user roles              │
│  - Apply @PreAuthorize rules    │
└─────────────────────────────────┘

Access Control Hierarchy

Employer (Admin)
    ├─ Manage stores
    ├─ Hire employees
    ├─ View all orders
    └─ Access analytics

Employee (Manager/Salesperson)
    ├─ Create orders
    ├─ Update own orders
    └─ View store inventory

📊 Database Schema (Key Entities)

Employer ◄──── Store ──────┬──► Category
  │                        │        │
  │                        └────────┼──► Product
  │                                 │       │
  ├──────► Employee ─────────────►  │       │
  │                                 │       ▼
  │                                 └──► Stock
  │
  └───────────────► Order ◄─────────────► OrderContent
                      │
                      └────────► Person (superclass)

🎓 Design Patterns Implemented

Pattern Location Purpose
Repository services.interfaces Data access abstraction
Service Locator SecurityValidator Centralized security rules
Strategy OrderStatus enum with switch Flexible state transitions
Decorator ResponseBuilder Consistent API responses
Factory JwtService Token generation
Singleton Spring @Component beans Single instance services

🤝 Contributing

This is a portfolio project showcasing enterprise-grade backend engineering. Contributions are welcome for educational purposes.


📝 License

This project is provided as-is for educational and portfolio demonstration purposes.


👨‍💻 Author

Developed with meticulous attention to:

  • Clean architecture principles
  • SOLID design patterns
  • Enterprise security standards
  • Production-ready code quality

📞 Contact & Support

For inquiries or technical discussions:


⭐ If you find this project interesting, please consider starring it to show your support!

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors