From c2badfe536322499eff2ca711b67c0dfeb7cffd7 Mon Sep 17 00:00:00 2001 From: prgres Date: Tue, 22 Jan 2019 02:42:50 +0100 Subject: [PATCH 01/12] added quantityChange validation, product validation, checking existing object in db, throwing exeption --- .idea/compiler.xml | 2 +- .idea/workspace.xml | 427 ++++++++++-------- pom.xml | 9 + .../sysmag/controller/ProductController.java | 64 ++- .../exception/ProductNotFoundException.java | 8 + .../com/dino/scrum/sysmag/model/Product.java | 21 + .../dino/scrum/sysmag/model/dto/IdDto.java | 1 + .../sysmag/model/dto/QuantityChange.java | 2 + .../sysmag/repository/ProductRepository.java | 13 +- .../scrum/sysmag/service/ProductService.java | 23 +- .../sysmag/service/ProductServiceImpl.java | 54 ++- .../sysmag/validator/ProductValidator.java | 38 ++ .../validator/QuantityChangeValidator.java | 44 ++ 13 files changed, 468 insertions(+), 238 deletions(-) create mode 100644 src/main/java/com/dino/scrum/sysmag/exception/ProductNotFoundException.java create mode 100644 src/main/java/com/dino/scrum/sysmag/validator/ProductValidator.java create mode 100644 src/main/java/com/dino/scrum/sysmag/validator/QuantityChangeValidator.java diff --git a/.idea/compiler.xml b/.idea/compiler.xml index bb087f3..09f7e11 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -9,7 +9,7 @@ - + diff --git a/.idea/workspace.xml b/.idea/workspace.xml index e7c6a5b..b9a1078 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,7 +2,20 @@ + + + + + + + + + + + + + + + - - + + - + - + - - + + - + - + @@ -388,7 +415,7 @@ - + @@ -452,78 +479,31 @@ - + - - + + - - + + - + - - - - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -537,10 +517,105 @@ - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index 83ac68a..613f30a 100644 --- a/pom.xml +++ b/pom.xml @@ -49,6 +49,15 @@ org.springframework.boot spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 11 + + diff --git a/src/main/java/com/dino/scrum/sysmag/controller/ProductController.java b/src/main/java/com/dino/scrum/sysmag/controller/ProductController.java index 3f0ce5e..84c6361 100644 --- a/src/main/java/com/dino/scrum/sysmag/controller/ProductController.java +++ b/src/main/java/com/dino/scrum/sysmag/controller/ProductController.java @@ -3,12 +3,15 @@ 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.ProductService; import com.dino.scrum.sysmag.service.ProductServiceImpl; +import com.dino.scrum.sysmag.validator.QuantityChangeValidator; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; +import javax.validation.Valid; import java.util.Collections; import java.util.Map; @@ -16,53 +19,70 @@ import java.util.Map; * Created by prgres on 2019-01-12. */ -@Controller +@RestController @RequestMapping(value = "/api") public class ProductController { - private final ProductServiceImpl productService; + private final + ProductServiceImpl productService; + private final + QuantityChangeValidator quantityChangeValidator; @Autowired - public ProductController(ProductServiceImpl productService) { + public ProductController(ProductServiceImpl productService, QuantityChangeValidator quantityChangeValidator) { this.productService = productService; + this.quantityChangeValidator = quantityChangeValidator; } @GetMapping(value = "/get-all") - public @ResponseBody - Iterable getAll(){ - return productService.getAllProducts(); + public Iterable getAll(Pageable pageable) { + return productService.getAll(pageable); } - @GetMapping(value = "/get-price-of-all") - public @ResponseBody + public Map getPriceOfAllProducts(){ - return Collections.singletonMap("price-of-all", productService.getPriceOfAllProducts()); + return Collections.singletonMap("price-of-all", productService.getPriceOfAll()); } @PostMapping(value = "/product/add") - public @ResponseBody - Product addProduct(@RequestBody Product product){ - return productService.addProduct(product); + 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 @ResponseBody + public String deleteProduct(@RequestBody IdDto id){ - productService.deleteProduct(id.getId()); - return "Deleted" + 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 @ResponseBody + public Product getById(@RequestBody IdDto id){ - return productService.getById(id.getId()); + try { + return productService.getById(id.getId()); + } catch (Exception e) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.toString()); + } } @PostMapping(value = "/product/change-quantity") - public @ResponseBody + public Product changeQuantity(@RequestBody QuantityChange quantityChange){ - return productService.changeQuantity(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 index bc2d178..d67df37 100644 --- a/src/main/java/com/dino/scrum/sysmag/model/Product.java +++ b/src/main/java/com/dino/scrum/sysmag/model/Product.java @@ -5,6 +5,10 @@ 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; /** @@ -23,16 +27,33 @@ public class Product { @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 index 0b5e89c..f8e2f26 100644 --- a/src/main/java/com/dino/scrum/sysmag/model/dto/IdDto.java +++ b/src/main/java/com/dino/scrum/sysmag/model/dto/IdDto.java @@ -8,5 +8,6 @@ import lombok.Getter; @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 index 62718fc..81d2881 100644 --- a/src/main/java/com/dino/scrum/sysmag/model/dto/QuantityChange.java +++ b/src/main/java/com/dino/scrum/sysmag/model/dto/QuantityChange.java @@ -1,5 +1,6 @@ package com.dino.scrum.sysmag.model.dto; +import lombok.EqualsAndHashCode; import lombok.Getter; /** @@ -7,6 +8,7 @@ import lombok.Getter; */ @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 index f1b5f0f..f9aebcb 100644 --- a/src/main/java/com/dino/scrum/sysmag/repository/ProductRepository.java +++ b/src/main/java/com/dino/scrum/sysmag/repository/ProductRepository.java @@ -1,16 +1,19 @@ package com.dino.scrum.sysmag.repository; import com.dino.scrum.sysmag.model.Product; -import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.stereotype.Repository; -import java.math.BigDecimal; -import java.util.List; import java.util.Optional; /** * Created by prgres on 2019-01-12. */ +@Repository +public interface ProductRepository extends PagingAndSortingRepository { + boolean existsByName(String name); -public interface ProductRepository extends CrudRepository { - List findAll(); + 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 index 869e29e..77434e9 100644 --- a/src/main/java/com/dino/scrum/sysmag/service/ProductService.java +++ b/src/main/java/com/dino/scrum/sysmag/service/ProductService.java @@ -2,19 +2,24 @@ package com.dino.scrum.sysmag.service; import com.dino.scrum.sysmag.model.Product; import com.dino.scrum.sysmag.model.dto.QuantityChange; - -import java.util.List; -import java.util.Optional; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; /** * Created by prgres on 2019-01-12. */ public interface ProductService { - List getAllProducts(); - Product changeQuantity(QuantityChange quantityChange); - Product getById(Long id); - float getPriceOfAllProducts(); - Product addProduct(Product product); - void deleteProduct(long id); + Slice getAll(Pageable pageable); + + Product changeQuantity(QuantityChange quantityChange) throws Exception; + + Product getById(Long id) throws Exception; + + Product add(Product product) 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 index 1c77e15..f1569ad 100644 --- a/src/main/java/com/dino/scrum/sysmag/service/ProductServiceImpl.java +++ b/src/main/java/com/dino/scrum/sysmag/service/ProductServiceImpl.java @@ -3,14 +3,15 @@ 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 javax.persistence.EntityNotFoundException; import java.math.BigDecimal; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; /** * Created by prgres on 2019-01-12. @@ -19,57 +20,60 @@ import java.util.stream.Collectors; @Service public class ProductServiceImpl implements ProductService { - private final ProductRepository productRepository; + private final + ProductRepository productRepository; + + private final + ProductValidator productValidator; @Autowired - public ProductServiceImpl(ProductRepository productRepository) { + public ProductServiceImpl(ProductRepository productRepository, ProductValidator productValidator) { this.productRepository = productRepository; + this.productValidator = productValidator; } @Override - public List getAllProducts() { - return productRepository.findAll(); + 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) { - return productRepository.findById(quantityChange.getId()) - .map(product -> { - product.setQuantity( - product.getQuantity() + quantityChange.getChange() - ); - return productRepository.save(product); - }).orElse(null); + 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) { - return productRepository.findById(id).orElse(null); + public Product getById(Long id) throws Exception { + productValidator.checkIfExists(id); + return productRepository.findById(id.longValue()); } @Override - public float getPriceOfAllProducts() { + public float getPriceOfAll() { BigDecimal result = new BigDecimal(0); - List tempProductList = productRepository.findAll(); + Iterable tempProductList = productRepository.findAll(); for (Product product : tempProductList) { result = result.add( product.getPrice() .multiply( new BigDecimal(product.getQuantity()))); } - return result.floatValue(); - } @Override - public Product addProduct(Product product) { + public Product add(Product product) throws Exception { + productValidator.checkIfExists(product.getName()); return productRepository.save(product); } @Override - public void deleteProduct(long id) { + public void delete(long id) throws Exception { + productValidator.checkIfExists(id); productRepository.deleteById(id); } - } 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 From d84674c6373a6f3e507735802521a4eb12a44f83 Mon Sep 17 00:00:00 2001 From: prgres Date: Tue, 22 Jan 2019 03:16:40 +0100 Subject: [PATCH 02/12] add update product and omitted validation --- .idea/dataSources.xml | 11 + .idea/workspace.xml | 341 ++++++++++-------- .../sysmag/controller/ProductController.java | 11 + .../scrum/sysmag/service/ProductService.java | 2 + .../sysmag/service/ProductServiceImpl.java | 28 +- .../sysmag/validationGroup/UpdateGroup.java | 8 + src/main/resources/application.properties | 2 +- target/classes/application.properties | 24 +- 8 files changed, 271 insertions(+), 156 deletions(-) create mode 100644 .idea/dataSources.xml create mode 100644 src/main/java/com/dino/scrum/sysmag/validationGroup/UpdateGroup.java diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000..e05b8fd --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,11 @@ + + + + + postgresql + true + org.postgresql.Driver + jdbc:postgresql://ec2-54-75-230-41.eu-west-1.compute.amazonaws.com:5432/d3e1jrm08qe91q?ssl=true&sslmode=require&amp=org.postgresql.ssl.NonValidatingFactory + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index b9a1078..5a575d6 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,20 +1,13 @@ - - - - - + + - - - - - + @@ -35,85 +28,113 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -428,7 +339,7 @@ - + + + + + + + + + @@ -473,11 +401,11 @@ - + - + - + @@ -538,13 +466,14 @@ - + - - - + + + + + + + + + From 02118fe1de7d27094ecd6acacef80a4b84fcfd03 Mon Sep 17 00:00:00 2001 From: prgres Date: Tue, 22 Jan 2019 04:33:32 +0100 Subject: [PATCH 06/12] ignore --- .gitignore | 50 ++++++++++++++++- .idea/workspace.xml | 53 ++++++++++++++----- target/classes/META-INF/sysmag.kotlin_module | Bin 0 -> 16 bytes 3 files changed, 87 insertions(+), 16 deletions(-) create mode 100644 target/classes/META-INF/sysmag.kotlin_module diff --git a/.gitignore b/.gitignore index 63c1976..129a20e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,10 @@ +application.properties + + +# Created by https://www.gitignore.io/api/java,intellij +# Edit at https://www.gitignore.io/?templates=java,intellij + +### Intellij ### # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 @@ -47,8 +54,6 @@ out/ # mpeltonen/sbt-idea plugin .idea_modules/ -*.properties - # JIRA plugin atlassian-ide-plugin.xml @@ -63,3 +68,44 @@ fabric.properties # Editor-based Rest Client .idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Intellij Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +.idea/sonarlint + +### Java ### +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ +git +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# End of https://www.gitignore.io/api/java,intellij \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 604ba13..e904c5d 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,9 +1,9 @@ - - - + + + - + - - + + @@ -103,11 +91,11 @@ - + - - + + @@ -124,15 +112,6 @@ - - - - - - - - - @@ -145,8 +124,8 @@ - - + + @@ -157,17 +136,29 @@ - - + + - + - - + + + + + + + + + + + + + + @@ -212,10 +203,11 @@ @@ -256,6 +248,7 @@ + @@ -274,6 +267,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -285,7 +320,6 @@