diff --git a/.idea/workspace.xml b/.idea/workspace.xml index e904c5d..02f0632 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,8 +2,21 @@ - - + + + + + + + + + + + + + + + - @@ -411,6 +424,7 @@ + @@ -686,8 +700,8 @@ - - + + diff --git a/src/main/java/com/dino/scrum/sysmag/SysmagApplication.java b/src/main/java/com/dino/scrum/sysmag/SysmagApplication.java new file mode 100644 index 0000000..20ce59f --- /dev/null +++ b/src/main/java/com/dino/scrum/sysmag/SysmagApplication.java @@ -0,0 +1,14 @@ +package com.dino.scrum.sysmag; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SysmagApplication { + + public static void main(String[] args) { + SpringApplication.run(SysmagApplication.class, args); + } + +} + diff --git a/src/main/java/com/dino/scrum/sysmag/controller/HomeController.java b/src/main/java/com/dino/scrum/sysmag/controller/HomeController.java new file mode 100644 index 0000000..2f5244b --- /dev/null +++ b/src/main/java/com/dino/scrum/sysmag/controller/HomeController.java @@ -0,0 +1,17 @@ +package com.dino.scrum.sysmag.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * Created by prgres on 2019-01-13. + */ + +@RestController +public class HomeController { + + @GetMapping("/") + public String home() { + return "System magazynowy"; + } +} diff --git a/src/main/java/com/dino/scrum/sysmag/controller/ProductController.java b/src/main/java/com/dino/scrum/sysmag/controller/ProductController.java new file mode 100644 index 0000000..e37fd44 --- /dev/null +++ b/src/main/java/com/dino/scrum/sysmag/controller/ProductController.java @@ -0,0 +1,95 @@ +package com.dino.scrum.sysmag.controller; + +import com.dino.scrum.sysmag.model.Product; +import com.dino.scrum.sysmag.model.dto.IdDto; +import com.dino.scrum.sysmag.model.dto.QuantityChange; +import com.dino.scrum.sysmag.service.ProductServiceImpl; +import com.dino.scrum.sysmag.validationGroup.UpdateGroup; +import com.dino.scrum.sysmag.validator.QuantityChangeValidator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; + +import javax.validation.Valid; +import java.util.Collections; +import java.util.Map; + +/** + * Created by prgres on 2019-01-12. + */ + +@RestController +@RequestMapping(value = "/api") +public class ProductController { + + private final + ProductServiceImpl productService; + private final + QuantityChangeValidator quantityChangeValidator; + + @Autowired + public ProductController(ProductServiceImpl productService, QuantityChangeValidator quantityChangeValidator) { + this.productService = productService; + this.quantityChangeValidator = quantityChangeValidator; + } + + @GetMapping(value = "/get-all") + public Iterable getAll(Pageable pageable) { + return productService.getAll(pageable); + } + + @GetMapping(value = "/get-price-of-all") + public Map getPriceOfAllProducts() { + return Collections.singletonMap("price-of-all", productService.getPriceOfAll()); + } + + @PostMapping(value = "/product/add") + public Product addProduct(@Valid @RequestBody Product product) { + try { + return productService.add(product); + } catch (Exception e) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.toString()); + } + } + + @DeleteMapping(value = "/product/delete") + public String deleteProduct(@RequestBody IdDto id) { + try { + productService.delete(id.getId()); + return "Deleted" + id; + } catch (Exception e) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.toString()); + } + } + + @GetMapping(value = "/product/get-by-id") + public Product getById(@RequestBody IdDto id) { + try { + return productService.getById(id.getId()); + } catch (Exception e) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.toString()); + } + } + + @PostMapping(value = "/product/update/{id}") + public Product update(@Validated(UpdateGroup.class) @RequestBody Product product, @PathVariable("id") long id) { + try { + return productService.update(product, id); + } catch (Exception e) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.toString()); + } + } + + @PostMapping(value = "/product/change-quantity") + public Product changeQuantity(@RequestBody QuantityChange quantityChange) { + try { + quantityChangeValidator.validate(quantityChange); + return productService.changeQuantity(quantityChange); + } catch (Exception e) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.toString()); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/dino/scrum/sysmag/exception/ProductNotFoundException.java b/src/main/java/com/dino/scrum/sysmag/exception/ProductNotFoundException.java new file mode 100644 index 0000000..bf339b6 --- /dev/null +++ b/src/main/java/com/dino/scrum/sysmag/exception/ProductNotFoundException.java @@ -0,0 +1,8 @@ +package com.dino.scrum.sysmag.exception; + +/** + * Created by prgres on 2019-01-21. + */ + +public class ProductNotFoundException extends ClassNotFoundException { +} diff --git a/src/main/java/com/dino/scrum/sysmag/model/Product.java b/src/main/java/com/dino/scrum/sysmag/model/Product.java new file mode 100644 index 0000000..d67df37 --- /dev/null +++ b/src/main/java/com/dino/scrum/sysmag/model/Product.java @@ -0,0 +1,59 @@ +package com.dino.scrum.sysmag.model; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import javax.persistence.*; +import javax.validation.constraints.DecimalMin; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.math.BigDecimal; + +/** + * Created by prgres on 2019-01-12. + */ + +@Getter +@Setter +@ToString +@Entity +@Table(name = "Product") +public class Product { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "id") + private Long id; + + @NotNull(message = "name cannot be null") + @Size(min = 2, message = "name cannot be shorter that 2") + @Column(name = "name") + private String name; + + @NotNull(message = "price cannot be null") + @DecimalMin(value = "0.00", message = "price cannot be under 0.00") + @Column(name = "price") + private BigDecimal price; + + @NotNull(message = "quantity cannot be null") + @Min(value = 0, message = "quantity cannot be under 0") + @Column(name = "quantity") + private long quantity; + + @NotNull(message = "quantityMax cannot be null") + @Min(value = 1, message = "quantityMax cannot be under 1") + @Column(name = "quantityMax") + private long quantityMax; + + @NotNull(message = "image_link cannot be null") + @Column(name = "image_link") + private String imageLink; + + public Product setChangeQuantity(long change) { + this.quantity += change; + return this; + } + +} diff --git a/src/main/java/com/dino/scrum/sysmag/model/dto/IdDto.java b/src/main/java/com/dino/scrum/sysmag/model/dto/IdDto.java new file mode 100644 index 0000000..f8e2f26 --- /dev/null +++ b/src/main/java/com/dino/scrum/sysmag/model/dto/IdDto.java @@ -0,0 +1,13 @@ +package com.dino.scrum.sysmag.model.dto; + +import lombok.Getter; + +/** + * Created by prgres on 2019-01-13. + */ + +@Getter +public class IdDto { + + long id; +} diff --git a/src/main/java/com/dino/scrum/sysmag/model/dto/QuantityChange.java b/src/main/java/com/dino/scrum/sysmag/model/dto/QuantityChange.java new file mode 100644 index 0000000..81d2881 --- /dev/null +++ b/src/main/java/com/dino/scrum/sysmag/model/dto/QuantityChange.java @@ -0,0 +1,15 @@ +package com.dino.scrum.sysmag.model.dto; + +import lombok.EqualsAndHashCode; +import lombok.Getter; + +/** + * Created by prgres on 2019-01-12. + */ + +@Getter +@EqualsAndHashCode +public class QuantityChange { + long id; + long change; +} diff --git a/src/main/java/com/dino/scrum/sysmag/repository/ProductRepository.java b/src/main/java/com/dino/scrum/sysmag/repository/ProductRepository.java new file mode 100644 index 0000000..f9aebcb --- /dev/null +++ b/src/main/java/com/dino/scrum/sysmag/repository/ProductRepository.java @@ -0,0 +1,19 @@ +package com.dino.scrum.sysmag.repository; + +import com.dino.scrum.sysmag.model.Product; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +/** + * Created by prgres on 2019-01-12. + */ +@Repository +public interface ProductRepository extends PagingAndSortingRepository { + boolean existsByName(String name); + + Optional findByName(String name); + + Product findById(long id); +} diff --git a/src/main/java/com/dino/scrum/sysmag/service/ProductService.java b/src/main/java/com/dino/scrum/sysmag/service/ProductService.java new file mode 100644 index 0000000..54824e0 --- /dev/null +++ b/src/main/java/com/dino/scrum/sysmag/service/ProductService.java @@ -0,0 +1,27 @@ +package com.dino.scrum.sysmag.service; + +import com.dino.scrum.sysmag.model.Product; +import com.dino.scrum.sysmag.model.dto.QuantityChange; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; + +/** + * Created by prgres on 2019-01-12. + */ + +public interface ProductService { + Slice getAll(Pageable pageable); + + Product changeQuantity(QuantityChange quantityChange) throws Exception; + + Product getById(Long id) throws Exception; + + Product add(Product product) throws Exception; + + Product update(Product product, long id) throws Exception; + + float getPriceOfAll(); + + void delete(long id) throws Exception; +} + diff --git a/src/main/java/com/dino/scrum/sysmag/service/ProductServiceImpl.java b/src/main/java/com/dino/scrum/sysmag/service/ProductServiceImpl.java new file mode 100644 index 0000000..d03533f --- /dev/null +++ b/src/main/java/com/dino/scrum/sysmag/service/ProductServiceImpl.java @@ -0,0 +1,105 @@ +package com.dino.scrum.sysmag.service; + +import com.dino.scrum.sysmag.model.Product; +import com.dino.scrum.sysmag.model.dto.QuantityChange; +import com.dino.scrum.sysmag.repository.ProductRepository; +import com.dino.scrum.sysmag.validator.ProductValidator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; + +/** + * Created by prgres on 2019-01-12. + */ + +@Service +public class ProductServiceImpl implements ProductService { + + private final + ProductRepository productRepository; + + private final + ProductValidator productValidator; + + @Autowired + public ProductServiceImpl(ProductRepository productRepository, ProductValidator productValidator) { + this.productRepository = productRepository; + this.productValidator = productValidator; + } + + @Override + public Slice getAll(Pageable pageable) { + if (pageable.getSort().isUnsorted()) { + pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), new Sort(Sort.Direction.ASC, "id")); + } + return productRepository.findAll(pageable); + } + + @Override + public Product changeQuantity(QuantityChange quantityChange) throws Exception { + productValidator.checkIfExists(quantityChange.getId()); + return productRepository.findById(quantityChange.getId()).setChangeQuantity(quantityChange.getChange()); + } + + @Override + public Product getById(Long id) throws Exception { + productValidator.checkIfExists(id); + return productRepository.findById(id.longValue()); + } + + @Override + public float getPriceOfAll() { + BigDecimal result = new BigDecimal(0); + Iterable tempProductList = productRepository.findAll(); + + for (Product product : tempProductList) { + result = result.add( + product.getPrice() + .multiply(new BigDecimal(product.getQuantity()))); + } + return result.floatValue(); + } + + @Override + public Product add(Product product) throws Exception { + productValidator.checkIfExists(product.getName()); + return productRepository.save(product); + } + + @Override + public Product update(Product productReceived, long id) throws Exception { + productValidator.checkIfExists(productReceived.getId()); + + Product productToChange = productRepository.findById(id); + + if (productReceived.getName() != null) + productToChange.setName(productReceived.getName()); + + if (productReceived.getName() != null) + productToChange.setPrice(productReceived.getPrice()); + + if (productReceived.getName() != null) + productToChange.setQuantity(productReceived.getQuantity()); + + if (productReceived.getName() != null) + productToChange.setQuantityMax(productReceived.getQuantityMax()); + + if (productReceived.getName() != null) + productToChange.setImageLink(productReceived.getImageLink()); + + productRepository.save(productToChange); + + return productRepository.findById(productToChange.getId().longValue()); + } + + @Override + public void delete(long id) throws Exception { + productValidator.checkIfExists(id); + productRepository.deleteById(id); + } +} diff --git a/src/main/java/com/dino/scrum/sysmag/validationGroup/UpdateGroup.java b/src/main/java/com/dino/scrum/sysmag/validationGroup/UpdateGroup.java new file mode 100644 index 0000000..5f8f3a5 --- /dev/null +++ b/src/main/java/com/dino/scrum/sysmag/validationGroup/UpdateGroup.java @@ -0,0 +1,8 @@ +package com.dino.scrum.sysmag.validationGroup; + +/** + * Created by prgres on 2019-01-22. + */ + +public interface UpdateGroup { +} diff --git a/src/main/java/com/dino/scrum/sysmag/validator/ProductValidator.java b/src/main/java/com/dino/scrum/sysmag/validator/ProductValidator.java new file mode 100644 index 0000000..45556dd --- /dev/null +++ b/src/main/java/com/dino/scrum/sysmag/validator/ProductValidator.java @@ -0,0 +1,38 @@ +package com.dino.scrum.sysmag.validator; + +import com.dino.scrum.sysmag.repository.ProductRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * Created by prgres on 2019-01-22. + */ + +@Component +public class ProductValidator { + + private final ProductRepository productRepository; + + @Autowired + public ProductValidator(ProductRepository productRepository) { + this.productRepository = productRepository; + } + + private boolean existsById(long id) { + return productRepository.existsById(id); + } + + private boolean existsByName(String name) { + return productRepository.existsByName(name); + } + + public void checkIfExists(long id) throws Exception { + if (existsById(id)) + throw new Exception("Product with id: " + id + " not found"); + } + + public void checkIfExists(String name) throws Exception { + if (existsByName(name)) + throw new Exception("Product " + name + " already exists"); + } +} diff --git a/src/main/java/com/dino/scrum/sysmag/validator/QuantityChangeValidator.java b/src/main/java/com/dino/scrum/sysmag/validator/QuantityChangeValidator.java new file mode 100644 index 0000000..915a051 --- /dev/null +++ b/src/main/java/com/dino/scrum/sysmag/validator/QuantityChangeValidator.java @@ -0,0 +1,44 @@ +package com.dino.scrum.sysmag.validator; + +import com.dino.scrum.sysmag.model.Product; +import com.dino.scrum.sysmag.model.dto.QuantityChange; +import com.dino.scrum.sysmag.service.ProductServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * Created by prgres on 2019-01-20. + */ + +@Component +public class QuantityChangeValidator { + + private final + ProductServiceImpl productService; + + @Autowired + public QuantityChangeValidator(ProductServiceImpl productService) { + this.productService = productService; + } + + public void validate(QuantityChange quantityChange) throws Exception { + + Product product = productService.getById(quantityChange.getId()); + + if (ifUnderStock(product.getQuantity(), quantityChange.getChange())) { + throw new RuntimeException("Too low product with id: " + quantityChange.getId() + " on stock"); + } + + if (ifAboveMaxLimitStock(product.getQuantity(), product.getQuantityMax(), quantityChange.getChange())) { + throw new RuntimeException("Over max quantity limit of product with id: " + quantityChange.getId()); + } + } + + private boolean ifUnderStock(long quantityOfProduct, long quantityChange) { + return ((quantityOfProduct + quantityChange) < 0); + } + + private boolean ifAboveMaxLimitStock(long quantityOfProduct, long maxQuantityOfProduct, long quantityChange) { + return ((quantityOfProduct + quantityChange) > maxQuantityOfProduct); + } +} \ No newline at end of file diff --git a/src/test/java/com/dino/scrum/sysmag/SysmagApplicationTests.java b/src/test/java/com/dino/scrum/sysmag/SysmagApplicationTests.java new file mode 100644 index 0000000..a646b1d --- /dev/null +++ b/src/test/java/com/dino/scrum/sysmag/SysmagApplicationTests.java @@ -0,0 +1,17 @@ +package com.dino.scrum.sysmag; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class SysmagApplicationTests { + + @Test + public void contextLoads() { + } + +} +