Stock Manager is a Java Spring application that allows you to manage: product stocks, supplier and customer orders, and your employees.
It was developed in the context of the Bachelor's thesis of Matthieu Brühwiler at the University of Applied Sciences Haaga-Helia in the spring of 2023.
This application is a starting point for a stock management system. It is possible to use it like this, but adapting it to your needs is recommended. You are free to modify the code as you wish. However, you must respect the license.
The application is a backend application that uses a MariaDB database. It is possible to interact with the system using the provided REST API. The author highly recommends using a front-end application to interact with the system. For the moment, the author has not developed a front-end application, but it is planned to do so in the future.
The application uses Java Spring 3.0.0.RELEASE framework. In order to run the application, you need to have the following components:
- Java JDK 17 or higher,
- MariaDB 10.10.0 or higher,
- Apache Maven 4.0.0 or higher,
- A web server that supports Jakarta EE. (For example, Apache Tomcat 10.0.0 or higher.)
The application may work with another version of the components, but it has not been tested.
This installation tutorial is based on an Apache Tomcat server on a Windows operating system. The adaptation to another server or operating system is left to the user.
As stated in the requirements, you must have a web server that supports Jakarta EE. For this tutorial, we will use an Apache Tomcat server 11.0.0. The installation of the server is not covered in this tutorial. You can find the installation instructions on the Apache Tomcat website.
To run the project, you must specify various information to the Spring Framework in a properties file.
In order to specify the environment variables to Apache Tomcat, you need to create a file named stockmanager.xml
in the [TOMCAT_INSTALLATION]/conf/Catalina/localhost
. This file should contain the following content:
<?xml version='1.0' encoding='utf-8'?>
<Context>
<Environment name="spring.config.location" value="file:PATH/TO/PROPERTIES/FILE/stockManager.properties" type="java.lang.String"/>
</Context>
The Spring application requires you to provide information about the profile, the database connection, the CORS properties, and the JWT properties. This file should be located in the PATH/TO/PROPERTIES/FILE
specified in the previous step.
Below is an example of a properties file:
# Profile (dev or prod)
spring.profiles.active=prod
# Database properties
spring.datasource.url=jdbc:mariadb://localhost:3306/stockmanagement
spring.datasource.username=root
spring.datasource.password=
spring.sql.init.mode=always
spring.jpa.defer-datasource-initialization=true
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
# Cors properties
spring.security.cors.allowed-origins=http://localhost:3000
spring.security.cors.allowed-methods=GET,POST,PUT,DELETE
spring.security.cors.allowed-headers=Authorization,Content-Type
# JWT properties
jwt.expiration.duration=8
jwt.expiration.unit=10
jwt.secret=THIS_IS_A_BAD_SECRET
To deploy the application on Apache Tomcat, you need to create a WAR file. As written in the requirements, the project is based on the Maven framework. Of this fact, to create the WAR file, you need to execute the following commands:
mvn clean package
mvn install
- The application contains several tests, and the duration of the tests can take 10 minutes. It is important not to skip the tests when creating the WAR file. If you skip the tests, the application may not work properly.*
After creating the WAR file named stockmanager.war
, you need to copy it into the [
TOMCAT_INSTALLATION]/webapps` folder.
At this point, you can now start the server. The Spring application manages by itself the database schema automatically. It will create, update, and delete the tables as needed.
To run the Apache Tomcat server, you must execute the catalina.bat
file located in the [TOMCAT_INSTALLATION]/bin
folder.
The application should be available at the following URL: http://IP_ADDRESS:8080/stockmanager/api
.
This chapter is an overview of the different endpoints of the application.
Before reading details about the endpoints, all of them have four common HTTP status codes:
- 200 / 201: The request has succeeded.
- 400: The request has failed because of a bad request.
- 401: The request has failed because the employee is not authenticated.
- 500: The request has failed because of an internal server error.
However, in the case of an error, whatever the status code is, the server always logs the error and returns a JSON object explaining the error.
Before using the application, you should consider the following properties:
- Some endpoints can be accessed depending on the employee's role.
- The application roles are:
- ROLE_ADMIN: id= 1
- ROLE_MANAGER: id= 2
- ROLE_EMPLOYEE: id= 3
- The application has a default admin user with the following credentials:
- username: main
- password: A1234
⚠️ This employee should be deactivated after the first connection.
It is important to note that most endpoints that return a list have paging, searching, and sorting methods. As in the following example: /api/brands?page=0&size=100&sort=name,asc&searchQuery=B.
- page: The page number.
- size: The number of elements per page.
- sort: The sorting method. The first parameter is the field to sort, and the second parameter is the sorting order (asc or desc).
- searchQuery: The search query.
To access the application, you need to be authenticated. The authentication is based on the JWT token.
Endpoint | Method | Description | Request Body | HTTP Status | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
/api/auth/login | POST | Authenticate an employee |
|
|
||||||||||||||||||
/api/auth/password | PUT | Change the password of an employee |
|
|
Endpoint | Method | Description | Request Body | HTTP Status | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
/api/employees | GET | Get the list of all the employees |
|
|||||||||||||||||||||||||||
/api/employees/{id} | GET | Get an employee by his/her id. |
|
|||||||||||||||||||||||||||
/api/employees | POST | Create a new employee. |
|
|
||||||||||||||||||||||||||
/api/employees/{id} | PUT | Modify an employee by his/her id. |
|
|
||||||||||||||||||||||||||
/api/employees/{id}/activate | PUT | Activate an employee id |
|
|||||||||||||||||||||||||||
/api/employees/{empId}/add-role/{roleId} | PUT | Assign a role to an employee. |
|
|||||||||||||||||||||||||||
/api/employees/{empId}/remove-role/{roleId} | PUT | Unassign a role to an employee. |
|
|||||||||||||||||||||||||||
/api/employees/{id} | DELETE | Deactivate an employee account. |
|
Endpoint | Method | Description | Request Body | HTTP Status | ||||||
---|---|---|---|---|---|---|---|---|---|---|
/api/statistics/suppliers?date={optionalDate} | GET | Get general statistics about suppliers. |
|
|||||||
/api/statistics/customers?date={optionalDate} | GET | Get general statistics about customers. |
|
|||||||
/api/statistics/employee={empId}?date={optionalDate} | GET | Calculate statistics for an employee on a defined month and year. |
|
|||||||
/api/statistics/stock-to-sale-ratio?date={optionalDate} | GET | Calculate the stock-to-sale ratio. |
|
|||||||
/api/statistics/sell-through-rate?date={optionalDate} | GET | Calculate the sell-through rate. |
|
|||||||
/api/statistics/stock-outs?date={optionalDate} | GET | Calculate the stock out rate. |
|
|||||||
/api/statistics/service-level | GET | Calculate the service level. |
|
Endpoint | Method | Description | Request Body | HTTP Status | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
/api/geolocations | GET | Get all the geolocations. |
|
|||||||||||||||||||||||||
/api/geolocations/{id} | GET | Get a geolocations by its id. |
|
|||||||||||||||||||||||||
/api/geolocations | POST | Create a new geolocation. |
|
|
||||||||||||||||||||||||
/api/geolocations | DELETE | Delete geolocation. |
|
Endpoint | Method | Description | Request Body | HTTP Status | |||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
/api/customers | GET | Get all the customers. |
|
||||||||||||||||||||||||
/api/customers/{email} | GET | Get a customer by his/her email. |
|
||||||||||||||||||||||||
/api/customers | POST | Create a new customer. |
|
|
|||||||||||||||||||||||
/api/customers/{email} | PUT | Update a customer. |
|
|
|||||||||||||||||||||||
/api/customers/{email} | DELETE | Delete a customer, but not his/her command(s). |
|
Endpoint | Method | Description | Request Body | HTTP Status | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
/api/customers/orders | GET | Get all the customer orders. |
|
|||||||||||||||||||||||
/api/customers/{customerId}/orders | GET | Get all the customer orders. |
|
|||||||||||||||||||||||
/api/customers/orders/{id} | GET | Get a customer order by its id. |
|
|||||||||||||||||||||||
/api/customers/orders | POST | Create a new customer order. |
|
|
||||||||||||||||||||||
/api/customers/orders/{id} | PUT | Update the delivery date of a customer order. |
|
|
||||||||||||||||||||||
/api/customers/orders/{id}/send | PUT | Change the state of the customer order as shipped. |
|
Endpoint | Method | Description | Request Body | HTTP Status | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
/api/customers/orders/order={orderId}/details | GET | Get all the customer order lines of a customer order. |
|
||||||||||||||||||||||
/api/customers/orders/order={orderId}/details/product={productId} | GET | Get a customer order line by its id. |
|
||||||||||||||||||||||
/api/customers/orders/order={orderId}/details/product={productId} | POST | Create a new customer order line. |
|
|
|||||||||||||||||||||
/api/customers/orders/order={orderId}/details/product={productId} | DELETE | Delete a customer order line. |
|
Endpoint | Method | Description | Request Body | HTTP Status | |||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
/api/suppliers/ | GET | Get all the suppliers. |
|
||||||||||||||||||||||||
/api/suppliers/{id} | GET | Get a supplier by its id. |
|
||||||||||||||||||||||||
/api/suppliers | POST | Create a new supplier. |
|
|
|||||||||||||||||||||||
/api/suppliers/{id} | PUT | Update a supplier. (email or phone number) |
|
|
|||||||||||||||||||||||
/api/suppliers/{id} | DELETE | Delete a supplier. |
|
Endpoint | Method | Description | Request Body | HTTP Status | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
/api/suppliers/orders | GET | Get all supplier orders. |
|
|||||||||||||||||||||||
/api/suppliers/{supplierId}/orders | GET | Get all supplier orders of a supplier. |
|
|||||||||||||||||||||||
/api/suppliers/orders/{id} | GET | Get a supplier order. |
|
|||||||||||||||||||||||
/api/suppliers/orders | POST | Create a supplier order. |
|
|
||||||||||||||||||||||
/api/suppliers/orders/{id} | PUT | Update a supplier order delivery date. |
|
|
||||||||||||||||||||||
/api/suppliers/orders/{id}/send | PUT | Update a supplier order to send. |
|
|||||||||||||||||||||||
/api/suppliers/orders/{id}/received | PUT | Receive a supplier order. |
|
|||||||||||||||||||||||
/api/suppliers/orders/{id}/cancel-reception | PUT | Cancel the reception of a supplier order. |
|
|||||||||||||||||||||||
/api/suppliers/orders/{id} | DELETE | Delete a supplier order. |
|
|||||||||||||||||||||||
/api/suppliers/orders/{id}/force | DELETE | Delete a supplier order by force. |
|
Endpoint | Method | Description | Request Body | HTTP Status | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
/api/suppliers/orders/order={orderId}/details | GET | Get all supplier order lines of a supplier order. |
|
||||||||||||||||||
api/suppliers/orders/order={orderId}/details/product={productId} | GET | Get a supplier order line of a supplier order. |
|
||||||||||||||||||
/api/suppliers/orders/order={orderId}/details/product={productId} | PUT | Update a supplier order line of a supplier order. |
|
|
|||||||||||||||||
/api/suppliers/orders/order={orderId}/details/product={productId} | DELETE | Delete a supplier order line of a supplier order. |
|
Endpoint | Method | Description | Request Body | HTTP Status | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
/api/brands | GET | Get all brands. |
|
|||||||||||||
/api/brands/{id} | GET | Get a brand. |
|
|||||||||||||
/api/brands | POST | Create a brand. |
|
|
||||||||||||
/api/brands/{id} | DELETE | Delete a brand. |
|
Endpoint | Method | Description | Request Body | HTTP Status | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
/api/categories | GET | Get all categories. |
|
||||||||||||||||
/api/categories/{id} | GET | Get a category. |
|
||||||||||||||||
/api/categories | POST | Create a category. |
|
|
|||||||||||||||
/api/categories/{id} | PUT | Update a category description. |
|
|
|||||||||||||||
/api/categories/{id} | DELETE | Delete a category. |
|
Endpoint | Method | Description | Request Body | HTTP Status | |||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
/api/products | GET | Get all products. |
|
||||||||||||||||||||||||||||||||||||||||||
/api/products/{id} | GET | Get a product. |
|
||||||||||||||||||||||||||||||||||||||||||
/api/products/{id}/details | GET | Get product details. |
|
||||||||||||||||||||||||||||||||||||||||||
/api/products/low | GET | Get all products with low stock. |
|
||||||||||||||||||||||||||||||||||||||||||
/api/products | POST | Create a product. |
|
|
|||||||||||||||||||||||||||||||||||||||||
/api/products/{id} | PUT | Update a product. |
|
|
|||||||||||||||||||||||||||||||||||||||||
/api/products/{id} | DELETE | Delete a product. |
|