diff --git a/backend/lab/build.gradle b/backend/lab/build.gradle index 329a229..be9945a 100644 --- a/backend/lab/build.gradle +++ b/backend/lab/build.gradle @@ -17,9 +17,10 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'com.h2database:h2:2.1.210' + implementation 'org.springframework.boot:spring-boot-starter-validation' implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.6.5' - + implementation 'org.hibernate.validator:hibernate-validator' testImplementation 'org.springframework.boot:spring-boot-starter-test' } diff --git a/backend/lab/data.mv.db b/backend/lab/data.mv.db index 76bc92a..8767b18 100644 Binary files a/backend/lab/data.mv.db and b/backend/lab/data.mv.db differ diff --git a/backend/lab/src/main/java/com/example/lab/DataBaseLab3/Models/Cart.java b/backend/lab/src/main/java/com/example/lab/DataBaseLab3/Models/Cart.java index f90bd57..c850381 100644 --- a/backend/lab/src/main/java/com/example/lab/DataBaseLab3/Models/Cart.java +++ b/backend/lab/src/main/java/com/example/lab/DataBaseLab3/Models/Cart.java @@ -1,7 +1,6 @@ package com.example.lab.DataBaseLab3.Models; import jakarta.persistence.*; -import jakarta.persistence.criteria.CriteriaBuilder; import java.util.*; @@ -12,79 +11,37 @@ public class Cart { @GeneratedValue(strategy = GenerationType.AUTO) private Long id; + @OneToMany + private List countProducts; @OneToOne private Customer customer; - @ManyToMany(fetch = FetchType.EAGER, mappedBy = "carts", cascade = CascadeType.ALL ) - private List products; //can't count there because of "integer not @entity" - @ElementCollection(fetch = FetchType.EAGER) - @CollectionTable(name = "cart_products_count", - joinColumns = {@JoinColumn(name = "cart_id", referencedColumnName = "id")}) - @MapKeyColumn(name = "product") - @Column(name = "amount") - private Map countProducts; //count amount of products public Cart(){} public Cart(Customer customer) { - this.countProducts = new HashMap<>(); + this.countProducts = new ArrayList<>(); this.customer = customer; } - public List getProducts() { - return products; - } - - public Map getCountProducts(){ - return countProducts; - } - - //изменяет ее значение если есть такой товар на +1 - public void addProduct(Product product){ - if(!countProducts.containsKey(product) || !products.contains(product)){ - this.countProducts.put(product, 1); - this.products.add(product); - } - else{ - countProducts.put(product, countProducts.get(product) + 1); - } - if (!product.getCarts().contains(this)){ - product.addCart(this); - } - } - - public void deleteProduct(Product product){ - products.remove(product); - if (product.getCarts().contains(this)) { - product.removeCart(this); - } - countProducts.remove(product); - } - - public void reduceProduct(Product product){ - if (!countProducts.containsKey(product)) return; - if(countProducts.get(product)==1){ - //delete the last one - deleteProduct(product); - } - else{ - countProducts.put(product, countProducts.get(product) - 1); - } - } @PreRemove public void deleteThis(){ - deleteAllProducts(); + //deleteAllProducts(); this.getCustomer().setCart(null); } - public void deleteAllProducts(){ - ArrayList products = new ArrayList<>(this.products); - this.countProducts.clear(); - this.products.clear(); - for (var product: - products) { - if (product.getCarts().contains(this)) product.removeCart(this); + public void addCountProduct(CountProduct countProduct){ + countProducts.add(countProduct); + if (countProduct.getCart() != this) { + countProduct.setCart(this); + } + } + + public void deleteCountProduct(CountProduct countProduct){ + countProducts.remove(countProduct); + if (countProduct.getCart() == this) { + countProduct.setCart(null); } } diff --git a/backend/lab/src/main/java/com/example/lab/DataBaseLab3/Models/CountProduct.java b/backend/lab/src/main/java/com/example/lab/DataBaseLab3/Models/CountProduct.java new file mode 100644 index 0000000..dce0c20 --- /dev/null +++ b/backend/lab/src/main/java/com/example/lab/DataBaseLab3/Models/CountProduct.java @@ -0,0 +1,87 @@ +package com.example.lab.DataBaseLab3.Models; +import jakarta.persistence.*; + +import java.util.*; + +@Entity +public class CountProduct { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @Column + private Integer amount; + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name="cart_fk") + private Cart cart; + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name="product_fk") + private Product product; + + public CountProduct(){} + + public CountProduct(Cart cart, Product product) { + this.cart = cart; + this.product = product; + this.amount = 0; + this.cart.addCountProduct(this); + this.product.addCountProduct(this); + } + + public void setProduct(Product product) { + this.product = product; + if (product != null && !product.getCountProducts().contains(this)){ + product.addCountProduct(this); + } + } + + public Cart getCart() { + return cart; + } + + public void setCart(Cart cart) { + this.cart = cart; + } + + public Product getProduct() { + return product; + } + + public int getAmount() { + return amount; + } + + public void setAmount(int amount) { + this.amount = amount; + } + + public void incrementAmount(){ + this.amount++; + } + + public void decrementAmount(){ + this.amount--; + } + + @PreRemove + public void deleteThis(){ + if(this.product !=null) this.product.deleteCountProduct(this); + if(this.cart !=null) this.cart.deleteCountProduct(this); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + CountProduct countProducts = (CountProduct) obj; + return Objects.equals(id, countProducts.id); + } + + @Override + public int hashCode(){ + return Objects.hashCode(id); + } +} + diff --git a/backend/lab/src/main/java/com/example/lab/DataBaseLab3/Models/Product.java b/backend/lab/src/main/java/com/example/lab/DataBaseLab3/Models/Product.java index b96f8f0..b73ddcf 100644 --- a/backend/lab/src/main/java/com/example/lab/DataBaseLab3/Models/Product.java +++ b/backend/lab/src/main/java/com/example/lab/DataBaseLab3/Models/Product.java @@ -3,7 +3,6 @@ package com.example.lab.DataBaseLab3.Models; import jakarta.persistence.*; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Objects; @@ -15,12 +14,9 @@ public class Product { private String name; private float price; + @OneToMany + private List countProducts; - @ManyToMany(fetch = FetchType.EAGER) - @JoinTable(name = "products_carts", - joinColumns = @JoinColumn(name = "product_fk"), - inverseJoinColumns = @JoinColumn(name = "cart_fk")) - private List carts; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "productCategory_fk") private ProductCategory productCategory; @@ -31,6 +27,7 @@ public class Product { this.name = name; this.price = price; this.productCategory = productCategory; + this.countProducts = new ArrayList<>(); } public ProductCategory getProductCategory() { @@ -67,40 +64,31 @@ public class Product { return price; } - - public void addCart(Cart cart) { - carts.add(cart); - if (!cart.getProducts().contains(this)) { - cart.addProduct(this); - } - - } @PreRemove public void deleteThis(){ - deleteAllCarts(); + //deleteAllCarts(); this.productCategory.getProducts().remove(this); } - public void deleteAllCarts(){ - ArrayList carts = new ArrayList<>(this.carts); - this.carts.clear(); - for (var cart: - carts) { - cart.deleteProduct(this); + + public List getCountProducts(){ + return countProducts; + } + + public void addCountProduct(CountProduct countProduct){ + countProducts.add(countProduct); + if (countProduct.getProduct() != this) { + countProduct.setProduct(this); } } - public void removeCart(Cart cart) { - carts.remove(cart); - if (cart.getProducts().contains(this)) { - cart.deleteAllProducts(); + public void deleteCountProduct(CountProduct countProduct){ + countProducts.remove(countProduct); + if (countProduct.getProduct() == this) { + countProduct.setProduct(null); } } - public List getCarts() { - return carts; - } - @Override public boolean equals(Object obj) { if (this == obj) return true; diff --git a/backend/lab/src/main/java/com/example/lab/DataBaseLab3/Services/CartService.java b/backend/lab/src/main/java/com/example/lab/DataBaseLab3/Services/CartService.java index f19d9c7..921f406 100644 --- a/backend/lab/src/main/java/com/example/lab/DataBaseLab3/Services/CartService.java +++ b/backend/lab/src/main/java/com/example/lab/DataBaseLab3/Services/CartService.java @@ -2,10 +2,10 @@ package com.example.lab.DataBaseLab3.Services; import com.example.lab.DataBaseLab3.Models.Customer; import com.example.lab.DataBaseLab3.Models.Product; +import com.example.lab.DataBaseLab3.Models.CountProduct; import jakarta.persistence.*; import jakarta.transaction.Transactional; import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; import com.example.lab.DataBaseLab3.Models.Cart; import java.util.List; @@ -15,9 +15,11 @@ public class CartService { private EntityManager em; private final ProductService productService; + private final CountProductService countProductService; - public CartService(ProductService productService){ + public CartService(ProductService productService, CountProductService countProductService){ this.productService = productService; + this.countProductService = countProductService; } @Transactional @@ -61,7 +63,9 @@ public class CartService { public Product addProduct(Long cartId, Long productId){ Product product = productService.getProduct(productId); Cart cart = getCart(cartId); - cart.addProduct(product); + var countProduct = countProductService.getCountProduct(productId, cartId); + if(countProduct == null) countProduct = countProductService.addCountProduct(product, cart); + countProduct.incrementAmount(); em.persist(cart); return product; } @@ -70,7 +74,9 @@ public class CartService { public Product deleteProduct(Long cartId, Long productId){ Product product = productService.getProduct(productId); Cart cart = getCart(cartId); - cart.deleteProduct(product); + var countProduct = countProductService.getCountProduct(productId, cartId); + if(countProduct == null) return null; + countProductService.deleteCountProduct(productId,cartId); em.persist(cart); return product; } @@ -79,7 +85,10 @@ public class CartService { public Product reduceProduct(Long cartId, Long productId){ Product product = productService.getProduct(productId); Cart cart = getCart(cartId); - cart.reduceProduct(product); + var countProduct = countProductService.getCountProduct(productId, cartId); + if(countProduct == null) return null; + countProduct.decrementAmount(); + em.persist(countProduct); return product; } } diff --git a/backend/lab/src/main/java/com/example/lab/DataBaseLab3/Services/CountProductService.java b/backend/lab/src/main/java/com/example/lab/DataBaseLab3/Services/CountProductService.java new file mode 100644 index 0000000..7fad59e --- /dev/null +++ b/backend/lab/src/main/java/com/example/lab/DataBaseLab3/Services/CountProductService.java @@ -0,0 +1,68 @@ +package com.example.lab.DataBaseLab3.Services; + +import com.example.lab.DataBaseLab3.Models.*; +import jakarta.persistence.*; +import jakarta.transaction.Transactional; +import org.springframework.stereotype.Service; +import com.example.lab.DataBaseLab3.Models.Product; + +import java.util.List; + +@Service +public class CountProductService { + @PersistenceContext + private EntityManager em; + + @Transactional + public CountProduct addCountProduct(Product product, + Cart cart){ + CountProduct countProduct = new CountProduct(cart, product); + em.persist(countProduct); + return countProduct; + } + + @Transactional + public CountProduct getCountProduct(long productId, long cartId){ + var count = getAllCountProducts(); + var countProduct = count.stream().filter(x -> x.getProduct().getId() == productId + && x.getCart().getId() == cartId ).findFirst(); + if(countProduct.isEmpty()) return null; + else return countProduct.get(); + } + + @Transactional + public CountProduct incrementProduct (long productId, long cartId){ + CountProduct countProduct = getCountProduct(productId, cartId); + countProduct.incrementAmount(); + return em.merge(countProduct); + } + + @Transactional + public CountProduct decrementProduct (long productId, long cartId){ + CountProduct countProduct = getCountProduct(productId, cartId); + countProduct.decrementAmount(); + return em.merge(countProduct); + } + + @Transactional + public CountProduct deleteCountProduct(long productId, long cartId){ + final CountProduct countProduct = getCountProduct(productId, cartId); + em.remove(countProduct); + return countProduct; + } + + @Transactional + public void deleteAll(){ + var list = getAllCountProducts(); + for (var cp: + list) { + cp.deleteThis(); + em.remove(cp); + } + } + + @Transactional + public List getAllCountProducts(){ + return em.createQuery("from CountProduct", CountProduct.class).getResultList(); + } +} \ No newline at end of file diff --git a/backend/lab/src/test/java/com/example/lab/DBTests.java b/backend/lab/src/test/java/com/example/lab/DBTests.java index 54fba11..9ba4eb1 100644 --- a/backend/lab/src/test/java/com/example/lab/DBTests.java +++ b/backend/lab/src/test/java/com/example/lab/DBTests.java @@ -1,13 +1,11 @@ package com.example.lab; -import com.example.lab.DataBaseLab3.Models.Cart; -import com.example.lab.DataBaseLab3.Models.Customer; -import com.example.lab.DataBaseLab3.Models.Product; -import com.example.lab.DataBaseLab3.Models.ProductCategory; +import com.example.lab.DataBaseLab3.Models.*; import com.example.lab.DataBaseLab3.Services.CartService; import com.example.lab.DataBaseLab3.Services.CustomerService; import com.example.lab.DataBaseLab3.Services.ProductCategoryService; import com.example.lab.DataBaseLab3.Services.ProductService; +import com.example.lab.DataBaseLab3.Services.CountProductService; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -23,6 +21,9 @@ public class DBTests { ProductCategoryService productCategoryService; @Autowired ProductService productService; + @Autowired + CountProductService countProductService; + @Test void testProductCategory(){ @@ -63,11 +64,9 @@ public class DBTests { @Test void testCustomer(){ cleanAll(); - Customer customer = customerService.addCustomer("Ivan", "Ivanov", "cityExample"); - Cart cart = cartService.addCart(customer); - Assertions.assertEquals("Ivan", customerService + Assertions.assertEquals("Ivan", customerService .getCustomer(customer.getId()).getFirstName()); Assertions.assertEquals("Ivanov", customerService .getCustomer(customer.getId()).getLastName()); @@ -101,7 +100,6 @@ public class DBTests { Cart cart = cartService.addCart(customer); Assertions.assertEquals(product,cartService.addProduct(cart.getId(), product.getId())); - Assertions.assertEquals(cart,cartService.getCart(cart.getId())); Assertions.assertEquals(product, cartService.reduceProduct(cart.getId(),product.getId())); Assertions.assertEquals(product, cartService.deleteProduct(cart.getId(),product.getId())); @@ -110,6 +108,7 @@ public class DBTests { } public void cleanAll(){ + countProductService.deleteAll(); productService.deleteAllProducts(); cartService.deleteAllCarts(); customerService.deleteAllCustomers();