Description

Order Management System
1.0 Introduction
In an e-commerce platform, administrators need an efficient way to manage product orders, including placing orders, managing inventory, and tracking order statuses. To automate this process, a RESTful service has been developed using Maven and Spring Boot to handle order-related operations as outlined below.


1.1 Functional Requirements
The system consists of an Order Management System that provides RESTful web services for handling orders, including placing new orders, checking inventory, and managing product stock.


2.0 Technical Specifications

OrderController
All the below endpoints return a ResponseEntity:

- For success - HttpStatus.OK

- For failure - Relevant HTTP status codes

Request Method

Request URL

Description

POST

/orders/place/{productId}/{quantity}

Places an order for a specified product and quantity using the placeOrder method in OrderServiceImpl.

 

Service Layer
The OrderServiceImpl class implements all required methods from the OrderService interface. This service layer manages all order-related operations using the OrderRepository, InventoryRepository, and ProductRepository.

Methods in OrderServiceImpl
Method

Description

Exception

placeOrder

Accepts productId and quantity as parameters. It first checks if the product exists in the database. If found, it verifies if sufficient stock is available. If stock is available, it deducts the required quantity and creates an order with status "PLACED". If there is insufficient stock, the order fails.

If the product is not found, an appropriate failure message is returned. If payment processing fails (simulated case), an exception is thrown.


Repository Layer
The repository layer consists of interfaces that interact with the database using Spring Data JPA:

Repository

Description

OrderRepository

Handles CRUD operations for the Order entity.

InventoryRepository

Manages stock levels and retrieves inventory data.

ProductRepository

Fetches product details based on product ID.

 

Model
The following entity classes define the database schema:

Product Class
Attribute

Data Type

productId

Long

name

String

price

double


Inventory Class
Attribute

Data Type

id

Long

productObj

Product (One-to-One relationship)

stock

int


Orders Class
Attribute

Data Type

id

Long

productObj

Product (Many-to-One relationship)

quantity

int

status

String ("PLACED" / "FAILED")


Note : id attribute in the orders class has to be auto generated.

3.0 Process Flow
1. Client invokes the required service.

2. OrderController calls the method in OrderServiceImpl.

3. OrderServiceImpl interacts with OrderRepository, InventoryRepository, and ProductRepository to perform the necessary operation.

4. The result is returned to the client.


4.0 Overall Design Constraints
- Do not change property names in application.properties. Additional properties can be added if needed.

- Dependencies required for the application are provided in pom.xml.

- Use Spring Data JPA for persistence.

- The primary key values for entities should not be automatically generated.

- Follow the expected service type and method names.

- The provided class and method names must not be changed.

- Ensure that there are no compilation errors in the final submission.


Note : When testing on your system using IDE, Use the below script and insert the records in the MySQL DB. 

USE test; 

INSERT INTO Product (product_id, name, price) VALUES 

(1, 'Laptop', 1200.50), (2, 'Smartphone', 799.99), (3, 'Tablet', 499.99), (4, 'Monitor', 249.99), (5, 'Keyboard', 49.99);


INSERT INTO Inventory (id, product_id, stock) VALUES 

(101, 1, 10), (102, 2, 20), (103, 3, 15), (104, 4, 25), (105, 5, 30);


package com.controller;

import com.service.OrderService;
import org.springframework.http.ResponseEntity;


//Provide necessary Annotation
public class OrderController {

    //Provide necessary Annotation
    private OrderService orderService;

 // Provide necessary Annotation and fill code in the below methods
    public ResponseEntity<String> placeOrder(Long productId,  int quantity) {
        // Fill the code here
        return null;
    }
}


package com.entity;

import jakarta.persistence.*;

//Provide necessary Annotation wherever necessary
public class Inventory {

   // Provide necessary Annotation
	private Long id;

	// Provide necessary Annotation
	private Product productObj;

	private int stock;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Product getProductObj() {
		return productObj;
	}

	public void setProductObj(Product productObj) {
		this.productObj = productObj;
	}

	public int getStock() {
		return stock;
	}

	public void setStock(int stock) {
		this.stock = stock;
	}

	public Inventory(Long id, Product productObj, int stock) {
		this.id = id;
		this.productObj = productObj;
		this.stock = stock;
	}

	public Inventory() {
	}
}


package com.entity;

import jakarta.persistence.*;

//Provide necessary Annotation wherever necessary
public class Product {

     // Provide necessary Annotation
    private Long productId;
    private String name;
    private double price;

    public Long getProductId() {
        return productId;
    }

    public void setProductId(Long productId) {
        this.productId = productId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public Product(Long productId, String name, double price) {
        this.productId = productId;
        this.name = name;
        this.price = price;
    }

    public Product() {
    }
}

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication
@EntityScan("com.entity")
@ComponentScan(basePackages={"com.repository","com.controller","com.entity","com.service","com.exception"})
@EnableJpaRepositories("com.repository")
public class ZOrderingApplication {

	public static void main(String[] args) {
		SpringApplication.run(ZOrderingApplication.class, args);
	}

}


package com.repository;

import com.entity.Inventory;
import com.entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface InventoryRepository extends JpaRepository<Inventory, Long> {
    Inventory findByProductObj(Product product);
}


package com.repository;

import com.entity.Orders;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface OrderRepository extends JpaRepository<Orders, Long> {
}


package com.repository;

import com.entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
    Product findByProductId(Long productId);
}


package com.service;

import com.entity.Inventory;
import com.entity.Orders;
import com.entity.Product;
import com.repository.InventoryRepository;
import com.repository.OrderRepository;
import com.repository.ProductRepository;
import org.springframework.stereotype.Service;

@Service
public class OrderService {

	  // Provide necessary Annotation
	private OrderRepository orderRepository;

	  // Provide necessary Annotation
	private InventoryRepository inventoryRepository;

	  // Provide necessary Annotation
	private ProductRepository productRepository;

	  // Provide necessary Annotation
	public String placeOrder(Long productId, int quantity) {
		//Fill the code


		 return null;
	}
}

spring.application.name=Z-Ordering
# Server Configuration
server.port=8080

# Database Configuration (MySQL example)
spring.datasource.url=jdbc:mysql://localhost:3306/test?createDatabaseIfNotExist=true
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# JPA Properties
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

# Hibernate Logging (optional, useful for debugging)
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

# Transaction Management
spring.transaction.default-timeout=30
spring.transaction.rollback-on-commit-failure=true


package com.entity;

import jakarta.persistence.*;

//Provide necessary Annotation wherever necessary
public class Orders {

    // Provide necessary Annotation
    private Long id;

    // Provide necessary Annotation
    private Product productObj;

    private int quantity;
    private String status; // "PLACED", "FAILED"

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Product getProductObj() {
        return productObj;
    }

    public void setProductObj(Product productObj) {
        this.productObj = productObj;
    }

    public int getQuantity() {
        return quantity;
    }

    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public Orders(Long id, Product productObj, int quantity, String status) {
        this.id = id;
        this.productObj = productObj;
        this.quantity = quantity;
        this.status = status;
    }

    public Orders() {
    }
}