Assume you are working for a software house producing applications for wholesale retailers specialized in office furniture. Your clients need software to support the process of selling goods to shops and chains.
You are working on the order module, and you get these requirements:
- there is a list of available Products, each with a standard price, a name.
- there is a list of Customers, some customers can have some Discount Agreements.
- discount agreements can be of the following types:
- X% off on a specific product.
- for a specific product, buy X, pay only for Y (for instance buy 3, pay only for 2 or buy 10, pay only for 9, etc).
- a customer gets X% off their order.
A user can create an Order for a Customer, and add some products to that order. For that they would specify which product and the quantity. They can then add new products, change the quantity for existing products, or remove products from the order. (very similar to the web-shop cart).
=> Make a program for calculating the total price of an order, taking into account the discount agreements of the Customer (for a product, if more than one discount apply, only one should be used, the one that gives the most rebate).
Focus on the modelling of the domain and the structure of the program, using good object programming principles and other programming patterns and practices. The program doesn't need to persist any data or have a User Interface, but we need to be able to verify that it works correctly. So, having UI and persisting data at least in in-memory could be feasible depending on how much you want to show your expertise.
Explain how the design would allow for these new requirements to be implemented:
- display the details of an order, indicating, if any, the discounts that have been applied. The output would need to support text and HTML.
- validate an order against a stock service.
- Products can have an optional category, and a new type of discount is: X% off products of a given category.
Explain how you would persist the model to a database with an ORM, what changes would be needed to the model, etc How would you create a report of the sum of the total price of the orders, grouped per month?
♻️ Constructing iterable as possible ♻️
- Been since i worked with ORM specifically, so decided to make some random comments on the way to form big image of things.
You are working on the order module.
- Using Java 9 Module structure. Since it was in specifications and its small program only one module is used. This was something new to me, so studied it and tried to apply it here. This can help compilation times for large projects.
⚠️ Do this after get normal workflow working. Seems like JPMS not fully support in Spring yet.- Make this in the end.
Display the details of an order, indicating, if any, the discounts that have been > applied. The output would need to support text and HTML.
- Showing data with Thymeleaf as HTML.
⚠️ Think about MVC pattern here, for now i went with good be practices. Got some template working for now, only one and best discount should show.
- Showing data as Text with Spring end point.
Validate an order against a stock service.
- There would be method
public boolean validateOrderAgainstExternalService(OrderDTO orderDTO)
in OrderServiceImpl which calls in the end@FeighClient
Or Other SpringBoot mechanisms(RestTemplate
,WebClient
) for calling external service.
Products can have an optional category, and a new type of discount is: X% off products of a given category.
- Products can have an optional category. null is no category specified.
- We use enum in categories since they are fixed and small.
⚠️ Todo Discount is: X% off products of a given category. Is handled in service layer.
A user can create an Order for a Customer, and add some products to that order. For that they would specify which product and the quantity. They can then add new products, change the quantity for existing products, or remove products from the order. (very similar to the web-shop cart).
- This is done trough smaller end points, rather than one big end point where body would accept Object.
- These is done in
OrderController
.
-
Entities till Service Layer.
- Business logic in Service Layer level. Such as Discount Rules. Not in Entity level.
-
⚠️ Todo Entities are validate to the business rule on service level. -
Entities will mostly use One-to-Many and Many-to-One relationships for convince for backend coding.
- Entities have some helper methods for managing bi-directional relationships. In general no logic should be inside entities.
⚠️ Todo add helpers methods for all bi-directional entities.
-
⚠️ Todo Indexing. -
⚠️ Todo Integration Tests. -
DTO are used for inside our business logic.
-
Will be using Repository over DAO, since its more common and it comes from Spring family.
-
Repository interfaces for each core entity:
CustomerRepository
,DiscountRepository
,OrderRepository
andProductRepository
.
-
Saving wil be done using
repository
since we have properly configured entity relationships. We can fully leverage Entity modifications, example trough JPA cascading.EntityManager
could be also used for fine-grained control over the persistence context, but for now went withRepositories
.
-
GlobalExceptionHandler
handles exceptions.- A GlobalExceptionHandler in a Spring Boot application provides a centralized way to handle exceptions.
- Spring Web Web for API:s.
- PostgreSQL Driver SQL for PostgreSQL database.
- Spring Data JPA SQL for PostgreSQL JDBC driver and data access layer.
- Spring Boot DevTools for fast development tools.
- Lombok for simplifies Java code by generating boilerplate.
- Spring Boot Thymeleaf for template engine for building server-side HTML-based views.
- Spring Cloud OpenFeign for declarative REST client support using Feign for HTTP communication.
Get the repository.
git clone https://github.com/developersCradle/office-furniture-selling-application.git
⚠️ Todo here, since real database is used. This works for now in development environment.
docker-compose up -d
- When there is database changes, sometimes its better redo whole database!
docker-compose down --volumes --remove-orphans
Retrieves a detailed report for the specified Order and returns a view for display.
- HTTP Method:
GET
Parameter | Type | Description | Required |
---|---|---|---|
orderId |
Long |
ID of the Order to retrieve. | Yes |
- HTTP Method:
GET
This endpoint retrieves a list of all customers in the database.
- Response: A list of customer, including the customer's ID and name. In JSON.
- HTTP Method:
DELETE
Removes a specific Product completely from an existing Order.
Parameter | Type | Description |
---|---|---|
orderId |
Long | The unique ID of the Order. |
orderItemInCartId |
Long | The unique ID of the OrderItemInCart in the Order. |
Add a totally new Product to an existing Order.
- HTTP Method:
POST
Parameter | Type | Description |
---|---|---|
orderId |
Long | The ID of the Order to which the Product will be added. |
Parameter | Type | Description |
---|---|---|
productId |
Long | The ID of the Product to be added to the order. |
quantity |
int | The quantity of the product to be added. |
Creates a new Order for the specified Customer. This is GET
for sake of simplicity.
- HTTP Method:
GET
Parameter | Type | Description | Required |
---|---|---|---|
customerId |
Long |
ID of the Customer for the Order. | Yes |
Updates the quantity of a specific OrderItemInCart in an Order.
- HTTP Method:
PUT
Parameter | Type | Description | Required |
---|---|---|---|
orderId |
Long |
ID of the Order to be updated. | Yes |
orderItemInCartId |
Long |
ID of the OrderItemInCartId to update. | Yes |
Parameter | Type | Description | Required |
---|---|---|---|
quantity |
int |
The new quantity for the item. This can be + or -. | Yes |
⚠️ Todo here.