Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 26 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.0</version>
<relativePath/> <!-- lookup parent from repository -->
<relativePath/>
</parent>
<groupId>com.encorazone</groupId>
<artifactId>inventory-manager</artifactId>
<version>0.0.1-SNAPSHOT</version>
<version>1.0.0</version>
<name>inventory-manager-spark</name>
<description>Demo project for Spring Boot</description>
<description>Inventory management application</description>
<url/>
<licenses>
<license/>
Expand All @@ -28,6 +28,9 @@
</scm>
<properties>
<java.version>17</java.version>
<ojdbc.version>21.3.0.0</ojdbc.version>
<springdoc.version>2.3.0</springdoc.version>
<lombok.version>1.18.38</lombok.version>
</properties>
<dependencies>
<dependency>
Expand All @@ -46,7 +49,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>${ojdbc.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
Expand All @@ -66,9 +73,22 @@
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
<version>${springdoc.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>

</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,51 +1,150 @@
package com.encorazone.inventory_manager.controller;

import com.encorazone.inventory_manager.domain.InventorySummaryResponse;
import com.encorazone.inventory_manager.domain.Product;
import com.encorazone.inventory_manager.service.ProductService;
import com.encorazone.inventory_manager.domain.ProductListResponse;
import com.encorazone.inventory_manager.domain.ProductShortResponse;
import com.encorazone.inventory_manager.service.InventoryService;

import org.springdoc.core.annotations.ParameterObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.UUID;

//@Controller
@CrossOrigin(origins = "http://localhost:3000")
@RestController
@RequestMapping("/products")
final class InventoryManagerController {

@Autowired
private ProductService productService;
private InventoryService inventoryService;

/**
* Edpoin to get all the elemnts from database, no sorting nor filtering
* Just pagination for the client usability
*
* @param page represents the page for the table. Example 0.
* @param size represents the number of elements per page, default is 10. Example 20.
* @return response status amd a list containing the pagexsize elements
*/
@GetMapping
public ResponseEntity<List<Product>> getAll(
@RequestParam(required = false) String filter,
@RequestParam(required = false) String sort,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
return ResponseEntity.ok(productService.getAll(filter, sort, page, size));
public ResponseEntity<ProductListResponse> getAll(
@RequestParam(required = false, defaultValue = "0") int page,
@RequestParam(required = false, defaultValue = "10") int size) {
return ResponseEntity.ok(inventoryService.getAll(page, size));
}

/**
* Endpoint for filtered data retrieving, including name, category and availability
* filtering from DB objects.
*
* @param name represent the name of the product. Example, Watermelon.
* @param category represents the category the element is part of; like food.
* @param stockQuantity represents the amount of elements in the inventory. Example 10.
* @param pageable Builtin object for sorting and pagination, the API asks for the json by itself
* @return responsse status and a list containing the pagexsixe elements
* complying with the sort and filter parameters
*/
@GetMapping("/filters")
public ResponseEntity<ProductListResponse> findByFilter(
@ModelAttribute @RequestParam(required = false) String name,
@ModelAttribute @RequestParam(required = false) String category,
@ModelAttribute @RequestParam(required = false, defaultValue = "0") Integer stockQuantity,
@ParameterObject Pageable pageable) {
return ResponseEntity.ok(inventoryService.findByNameAndCategoryAndStockQuantity(
name, category, stockQuantity, pageable));
}

/**
* Endpoint to create a new product
*
* @param product object representing the product to be added to the inventory
* @return status. Example 200(OK)
*/
@PostMapping
public ResponseEntity<Product> create(@RequestBody Product product) {
return ResponseEntity.ok(productService.create(product));
public ResponseEntity<ProductShortResponse> create(@RequestBody Product product) {
return ResponseEntity.ok(inventoryService.create(product));
}

/**
* endpoint to update a product
*
* @param id represents the DB/BS internal id fro managing elements.
* Example 785c0229-b7e5-4ea4-853b-fa5ad4eb84f4
* @param product Object with the changes fto be made to the product
* @return status. Example 500 (Internal server error)
*/
@PutMapping("/{id}")
public ResponseEntity<Product> update(@PathVariable Long id, @RequestBody Product product) {
return productService.update(id, product)
public ResponseEntity<ProductShortResponse> update(@PathVariable UUID id, @RequestBody Product product) {
return inventoryService.update(id, product)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}

/**
* endpoint to automatically set stock to 0
*
* @param id Represents the id of the element we want the stock to be 0
* @return status. Example 200
*/
@PatchMapping("/{id}/outofstock")
public ResponseEntity<ProductShortResponse> markOutOfStock(@PathVariable UUID id) {
return inventoryService.markOutOfStock(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}

@PostMapping("/{id}/outofstock")
public ResponseEntity<Product> markOutOfStock(@PathVariable Long id) {
return productService.markOutOfStock(id)
/**
* endpoint to automatically set stock to a given number, By default 10
*
* @param id Represents the id of the element we want the stock to be 0
* @param stockQuantity Represents the amount to put into stock. Example 10
* @return status. Example 200(OK)
*/
@PatchMapping("/{id}/instock")
public ResponseEntity<ProductShortResponse> restoreStock(@PathVariable UUID id,
@RequestParam(defaultValue = "10") Integer stockQuantity) {
return inventoryService.updateStock(id, stockQuantity)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}

/**
* Endpoint to delete products
*
* @param id Represemts tje id of the element to be deleted
* @return status code
*/
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteProduct(@PathVariable UUID id) {
inventoryService.delete(id);
return ResponseEntity.noContent().build();
}

/**
* Endpoint to retrieve categories
*
* @return list with the categories
*/
@GetMapping("/categories")
public ResponseEntity<List<String>> fetchCategories() {
return inventoryService.fetchCategories()
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}

@PutMapping("/{id}/instock")
public ResponseEntity<Product> restoreStock(@PathVariable Long id) {
return productService.restoreStock(id)
/**
* Endpoint to retrieve inventory summary
*
* @return list with the summary
*/
@GetMapping("/summary")
public ResponseEntity<List<InventorySummaryResponse>> fetchSummary() {
return inventoryService.fetchInventorySummary()
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.encorazone.inventory_manager.domain;

import java.math.BigDecimal;

public interface InventorySummaryInterface {
String getCategory();
Long getProductsInStock();
BigDecimal getValueInStock();
BigDecimal getAverageValue();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.encorazone.inventory_manager.domain;

import lombok.Data;

import java.math.BigDecimal;

@Data
public class InventorySummaryResponse{
private String category;

private Integer productsInStock;

private BigDecimal valueInStock;

private BigDecimal averageValue;

public InventorySummaryResponse(String category, long productsInStock, BigDecimal valueInStock,
BigDecimal averageValue) {
this.category = category;
this.productsInStock = (int) productsInStock;
this.valueInStock = valueInStock;
this.averageValue = averageValue;
}
}
87 changes: 16 additions & 71 deletions src/main/java/com/encorazone/inventory_manager/domain/Product.java
Original file line number Diff line number Diff line change
@@ -1,35 +1,42 @@
package com.encorazone.inventory_manager.domain;

import jakarta.persistence.*;
import lombok.Data;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.UUID;

@Data
@Entity
@Table(name = "products")
@Table(name = "PRODUCTS")
public class Product {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@GeneratedValue(generator = "uuid2")
@Column(name = "ID", columnDefinition = "RAW(16)")
private UUID id;

@Column(nullable = false, length = 120)
@Column(nullable = false, length = 120, name = "NAME")
private String name;

@Column(nullable = false)
@Column(nullable = false, name = "CATEGORY")
private String category;

@Column(nullable = false)
@Column(nullable = false, name = "UNIT_PRICE")
private BigDecimal unitPrice;

@Column(name = "EXPIRATION_DATE")
private LocalDate expirationDate;

@Column(nullable = false)
private Integer quantityInStock;
@Column(nullable = false, name = "STOCK_QUANTITY")
private Integer stockQuantity;

@Column(updatable = false)
@Column(updatable = false, name = "CREATION_DATE")
private LocalDateTime creationDate;

@Column(name = "UPDATE_DATE")
private LocalDateTime updateDate;

@PrePersist
Expand All @@ -43,67 +50,5 @@ public void onUpdate() {
updateDate = LocalDateTime.now();
}

public Long getId() {
return id;
}

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

public String getName() {
return name;
}

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

public String getCategory() {
return category;
}

public void setCategory(String category) {
this.category = category;
}

public BigDecimal getUnitPrice() {
return unitPrice;
}

public void setUnitPrice(BigDecimal unitPrice) {
this.unitPrice = unitPrice;
}

public LocalDate getExpirationDate() {
return expirationDate;
}

public void setExpirationDate(LocalDate expirationDate) {
this.expirationDate = expirationDate;
}

public Integer getQuantityInStock() {
return quantityInStock;
}

public void setQuantityInStock(Integer quantityInStock) {
this.quantityInStock = quantityInStock;
}

public LocalDateTime getCreationDate() {
return creationDate;
}

public void setCreationDate(LocalDateTime creationDate) {
this.creationDate = creationDate;
}

public LocalDateTime getUpdateDate() {
return updateDate;
}

public void setUpdateDate(LocalDateTime updateDate) {
this.updateDate = updateDate;
}
}
Loading