From b68ca63482699b23ce51c47aeecf142a04f5240a Mon Sep 17 00:00:00 2001 From: Bogdan <97698639+don-bigdad@users.noreply.github.com> Date: Thu, 2 Nov 2023 00:26:37 +0200 Subject: [PATCH 1/5] some work first commit --- .../controller/CartController.java | 5 +++ .../springbootbookshop/entity/Cart.java | 37 ++++++++++++++++ .../springbootbookshop/entity/CartItem.java | 33 ++++++++++++++ .../springbootbookshop/entity/User.java | 4 ++ .../changes/07-create-carts-table.yaml | 33 ++++++++++++++ .../changes/08-create-cart-items-table.yaml | 43 +++++++++++++++++++ 6 files changed, 155 insertions(+) create mode 100644 src/main/java/com/example/springbootbookshop/controller/CartController.java create mode 100644 src/main/java/com/example/springbootbookshop/entity/Cart.java create mode 100644 src/main/java/com/example/springbootbookshop/entity/CartItem.java create mode 100644 src/main/resources/db/changelog/changes/07-create-carts-table.yaml create mode 100644 src/main/resources/db/changelog/changes/08-create-cart-items-table.yaml diff --git a/src/main/java/com/example/springbootbookshop/controller/CartController.java b/src/main/java/com/example/springbootbookshop/controller/CartController.java new file mode 100644 index 0000000..d4d12f7 --- /dev/null +++ b/src/main/java/com/example/springbootbookshop/controller/CartController.java @@ -0,0 +1,5 @@ +package com.example.springbootbookshop.controller; + +public class CartController { + //todo:realise controller for cart +} diff --git a/src/main/java/com/example/springbootbookshop/entity/Cart.java b/src/main/java/com/example/springbootbookshop/entity/Cart.java new file mode 100644 index 0000000..cd4beb8 --- /dev/null +++ b/src/main/java/com/example/springbootbookshop/entity/Cart.java @@ -0,0 +1,37 @@ +package com.example.springbootbookshop.entity; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import java.util.Set; +import lombok.Data; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; + +@Entity +@Data +@SQLDelete(sql = "UPDATE carts SET is_deleted = true WHERE id = ?") +@Where(clause = "is_deleted=false") +@Table(name = "carts") +public class Cart { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToOne + @JoinColumn(name = "user_id", nullable = false) + private User user; + + @OneToMany(mappedBy = "cart",cascade = CascadeType.REMOVE) + private Set cartItems; + + @Column(nullable = false) + private boolean isDeleted = false; +} diff --git a/src/main/java/com/example/springbootbookshop/entity/CartItem.java b/src/main/java/com/example/springbootbookshop/entity/CartItem.java new file mode 100644 index 0000000..b701cf0 --- /dev/null +++ b/src/main/java/com/example/springbootbookshop/entity/CartItem.java @@ -0,0 +1,33 @@ +package com.example.springbootbookshop.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Entity +@Data +@Table(name = "cart_items") +public class CartItem { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne + @JoinColumn(name = "cart_id",nullable = false) + private Cart cart; + + @ManyToOne + @Column(nullable = false) + private Book book; + + @Column(nullable = false) + @NotNull + private int quantity; +} diff --git a/src/main/java/com/example/springbootbookshop/entity/User.java b/src/main/java/com/example/springbootbookshop/entity/User.java index dd0b251..98954b6 100644 --- a/src/main/java/com/example/springbootbookshop/entity/User.java +++ b/src/main/java/com/example/springbootbookshop/entity/User.java @@ -1,5 +1,6 @@ package com.example.springbootbookshop.entity; +import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -8,6 +9,7 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.JoinTable; import jakarta.persistence.ManyToMany; +import jakarta.persistence.OneToOne; import jakarta.persistence.Table; import java.util.Collection; import java.util.HashSet; @@ -50,6 +52,8 @@ public class User implements UserDetails { private Set roles = new HashSet<>(); @Column(nullable = false) private boolean isDeleted = false; + @OneToOne(mappedBy = "user",cascade = CascadeType.REMOVE) + private Cart cart; @Override public Collection getAuthorities() { diff --git a/src/main/resources/db/changelog/changes/07-create-carts-table.yaml b/src/main/resources/db/changelog/changes/07-create-carts-table.yaml new file mode 100644 index 0000000..fd2224c --- /dev/null +++ b/src/main/resources/db/changelog/changes/07-create-carts-table.yaml @@ -0,0 +1,33 @@ +databaseChangeLog: + - changeSet: + id: create-carts-table + author: bohdan-maksymenko + changes: + - createTable: + tableName: carts + columns: + - column: + name: id + type: BIGINT + constraints: + primaryKey: true + nullable: false + autoIncrement: true + - column: + name: user_id + type: BIGINT + constraints: + nullable: false + - column: + name: is_deleted + type: BOOLEAN + constraints: + nullable: false + defaultValueBoolean: false + - addForeignKeyConstraint: + baseTableName: carts + baseColumnNames: user_id + referencedTableName: users + referencedColumnNames: id + constraintName: FK_carts_user + onDelete: CASCADE diff --git a/src/main/resources/db/changelog/changes/08-create-cart-items-table.yaml b/src/main/resources/db/changelog/changes/08-create-cart-items-table.yaml new file mode 100644 index 0000000..1cebb1d --- /dev/null +++ b/src/main/resources/db/changelog/changes/08-create-cart-items-table.yaml @@ -0,0 +1,43 @@ +databaseChangeLog: + - changeSet: + id: create-cart-items-table + author: bohdan-maksymenko + changes: + - createTable: + tableName: cart_items + columns: + - column: + name: id + type: BIGINT + constraints: + primaryKey: true + nullable: false + autoIncrement: true + - column: + name: cart_id + type: BIGINT + constraints: + nullable: false + - column: + name: book_id + type: BIGINT + constraints: + nullable: false + - column: + name: quantity + type: INTEGER + constraints: + nullable: false + - addForeignKeyConstraint: + baseTableName: cart_items + baseColumnNames: cart_id + referencedTableName: carts + referencedColumnNames: id + constraintName: FK_cart_items_cart + onDelete: CASCADE + - addForeignKeyConstraint: + baseTableName: cart_items + baseColumnNames: book_id + referencedTableName: books + referencedColumnNames: id + constraintName: FK_cart_items_book From 813aa82cb29a1ba254e97efd6cd41ce6371aed85 Mon Sep 17 00:00:00 2001 From: Bogdan <97698639+don-bigdad@users.noreply.github.com> Date: Thu, 2 Nov 2023 00:40:24 +0200 Subject: [PATCH 2/5] mvn fixes need to test --- .../springbootbookshop/entity/CartItem.java | 4 ++-- .../springbootbookshop/entity/User.java | 1 + .../09-add-cart-id-to-users-table.yaml | 19 +++++++++++++++++++ .../db/changelog/db.changelog-master.yaml | 6 +++++- 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 src/main/resources/db/changelog/changes/09-add-cart-id-to-users-table.yaml diff --git a/src/main/java/com/example/springbootbookshop/entity/CartItem.java b/src/main/java/com/example/springbootbookshop/entity/CartItem.java index b701cf0..8eba2cc 100644 --- a/src/main/java/com/example/springbootbookshop/entity/CartItem.java +++ b/src/main/java/com/example/springbootbookshop/entity/CartItem.java @@ -20,11 +20,11 @@ public class CartItem { private Long id; @ManyToOne - @JoinColumn(name = "cart_id",nullable = false) + @JoinColumn(name = "cart_id", nullable = false) private Cart cart; @ManyToOne - @Column(nullable = false) + @JoinColumn(name = "book_id", nullable = false) private Book book; @Column(nullable = false) diff --git a/src/main/java/com/example/springbootbookshop/entity/User.java b/src/main/java/com/example/springbootbookshop/entity/User.java index 98954b6..316e4e5 100644 --- a/src/main/java/com/example/springbootbookshop/entity/User.java +++ b/src/main/java/com/example/springbootbookshop/entity/User.java @@ -52,6 +52,7 @@ public class User implements UserDetails { private Set roles = new HashSet<>(); @Column(nullable = false) private boolean isDeleted = false; + @OneToOne(mappedBy = "user",cascade = CascadeType.REMOVE) private Cart cart; diff --git a/src/main/resources/db/changelog/changes/09-add-cart-id-to-users-table.yaml b/src/main/resources/db/changelog/changes/09-add-cart-id-to-users-table.yaml new file mode 100644 index 0000000..dc34e87 --- /dev/null +++ b/src/main/resources/db/changelog/changes/09-add-cart-id-to-users-table.yaml @@ -0,0 +1,19 @@ +databaseChangeLog: + - changeSet: + id: add-cart-id-column-to-users + author: bohdan-maksymenko + changes: + - addColumn: + tableName: users + columns: + - column: + name: cart_id + type: BIGINT + constraints: + nullable: true + - addForeignKeyConstraint: + baseTableName: users + baseColumnNames: cart_id + referencedTableName: carts + referencedColumnNames: id + constraintName: FK_users_cart diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 471d7d5..dec3f5c 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -10,4 +10,8 @@ databaseChangeLog: - include: file: db/changelog/changes/05-create-category-table.yaml - include: - file: db/changelog/changes/06-create-books-categories-table.yaml \ No newline at end of file + file: db/changelog/changes/06-create-books-categories-table.yaml + - include: + file: db/changelog/changes/07-create-carts-table.yaml + - include: + file: db/changelog/changes/08-create-cart-items-table.yaml \ No newline at end of file From 5a9aa9f291bb30ea8e9cefb02f959debb8a9e17c Mon Sep 17 00:00:00 2001 From: Bogdan <97698639+don-bigdad@users.noreply.github.com> Date: Sat, 11 Nov 2023 14:25:39 +0200 Subject: [PATCH 3/5] implement logic for item in user cart --- .../controller/CartController.java | 70 ++++++++++++++++- .../springbootbookshop/dto/cart/CartDto.java | 9 +++ .../dto/cart/item/CartItemDto.java | 7 ++ .../dto/cart/item/RequestCartItemDto.java | 7 ++ .../cart/item/UpdateRequestCartItemDto.java | 7 ++ .../springbootbookshop/entity/Book.java | 7 ++ .../springbootbookshop/entity/Cart.java | 7 +- .../springbootbookshop/entity/CartItem.java | 8 +- .../springbootbookshop/entity/User.java | 5 -- .../mapper/CartItemMapper.java | 21 +++++ .../springbootbookshop/mapper/CartMapper.java | 23 ++++++ .../repository/CartItemsRepository.java | 15 ++++ .../repository/CartRepository.java | 14 ++++ .../service/CartService.java | 16 ++++ .../service/impl/CartServiceImpl.java | 78 +++++++++++++++++++ .../service/impl/CategoryServiceImpl.java | 4 +- .../service/impl/UserServiceImpl.java | 13 +++- .../changes/07-create-carts-table.yaml | 4 +- .../changes/08-create-cart-items-table.yaml | 17 +--- 19 files changed, 302 insertions(+), 30 deletions(-) create mode 100644 src/main/java/com/example/springbootbookshop/dto/cart/CartDto.java create mode 100644 src/main/java/com/example/springbootbookshop/dto/cart/item/CartItemDto.java create mode 100644 src/main/java/com/example/springbootbookshop/dto/cart/item/RequestCartItemDto.java create mode 100644 src/main/java/com/example/springbootbookshop/dto/cart/item/UpdateRequestCartItemDto.java create mode 100644 src/main/java/com/example/springbootbookshop/mapper/CartItemMapper.java create mode 100644 src/main/java/com/example/springbootbookshop/mapper/CartMapper.java create mode 100644 src/main/java/com/example/springbootbookshop/repository/CartItemsRepository.java create mode 100644 src/main/java/com/example/springbootbookshop/repository/CartRepository.java create mode 100644 src/main/java/com/example/springbootbookshop/service/CartService.java create mode 100644 src/main/java/com/example/springbootbookshop/service/impl/CartServiceImpl.java diff --git a/src/main/java/com/example/springbootbookshop/controller/CartController.java b/src/main/java/com/example/springbootbookshop/controller/CartController.java index d4d12f7..b17d46e 100644 --- a/src/main/java/com/example/springbootbookshop/controller/CartController.java +++ b/src/main/java/com/example/springbootbookshop/controller/CartController.java @@ -1,5 +1,73 @@ package com.example.springbootbookshop.controller; +import com.example.springbootbookshop.dto.cart.CartDto; +import com.example.springbootbookshop.dto.cart.item.CartItemDto; +import com.example.springbootbookshop.dto.cart.item.RequestCartItemDto; +import com.example.springbootbookshop.dto.cart.item.UpdateRequestCartItemDto; +import com.example.springbootbookshop.entity.User; +import com.example.springbootbookshop.service.CartService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Positive; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@RequiredArgsConstructor +@Tag(name = "Cart management",description = "Endpoints for managing carts") +@RestController +@Validated +@RequestMapping(value = "/cart") public class CartController { - //todo:realise controller for cart + private final CartService cartService; + + @GetMapping + @Operation(summary = "Get cart by user id from DB") + @PreAuthorize("hasRole('USER')") + public CartDto getUserCart(Authentication authentication) { + return cartService.findById(getUserId(authentication)); + } + + @PostMapping + @Operation(summary = "Add books to the user cart") + @PreAuthorize("hasRole('USER')") + public CartItemDto addItemToCart(Authentication authentication, + @Valid @RequestBody RequestCartItemDto cartItem) { + return cartService.addItemToCart(getUserId(authentication), cartItem); + } + + @DeleteMapping(value = "cart-items/{id}") + @Operation(summary = "Delete cart item from the user cart") + @PreAuthorize("hasRole('USER')") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void removeCartItem(Authentication authentication, + @PathVariable @Positive Long id) { + cartService.removeItem(id); + } + + @PutMapping(value = "cart-items/{id}") + @Operation(summary = "Update cart item in the user cart") + @PreAuthorize("hasRole('USER')") + @ResponseStatus(HttpStatus.OK) + public CartItemDto updateItemQuantity(@PathVariable @Positive Long id, + @RequestBody UpdateRequestCartItemDto quantity) { + return cartService.updateCartItem(id, quantity); + } + + private Long getUserId(Authentication authentication) { + User user = (User) authentication.getPrincipal(); + return user.getId(); + } } diff --git a/src/main/java/com/example/springbootbookshop/dto/cart/CartDto.java b/src/main/java/com/example/springbootbookshop/dto/cart/CartDto.java new file mode 100644 index 0000000..c679204 --- /dev/null +++ b/src/main/java/com/example/springbootbookshop/dto/cart/CartDto.java @@ -0,0 +1,9 @@ +package com.example.springbootbookshop.dto.cart; + +import com.example.springbootbookshop.dto.cart.item.CartItemDto; +import java.util.Set; + +public record CartDto(Long id, + Long userId, + Set cartItems) { +} diff --git a/src/main/java/com/example/springbootbookshop/dto/cart/item/CartItemDto.java b/src/main/java/com/example/springbootbookshop/dto/cart/item/CartItemDto.java new file mode 100644 index 0000000..1637b28 --- /dev/null +++ b/src/main/java/com/example/springbootbookshop/dto/cart/item/CartItemDto.java @@ -0,0 +1,7 @@ +package com.example.springbootbookshop.dto.cart.item; + +public record CartItemDto(Long id, + Long bookId, + String bookTitle, + Integer quantity){ +} diff --git a/src/main/java/com/example/springbootbookshop/dto/cart/item/RequestCartItemDto.java b/src/main/java/com/example/springbootbookshop/dto/cart/item/RequestCartItemDto.java new file mode 100644 index 0000000..a4bbb51 --- /dev/null +++ b/src/main/java/com/example/springbootbookshop/dto/cart/item/RequestCartItemDto.java @@ -0,0 +1,7 @@ +package com.example.springbootbookshop.dto.cart.item; + +import jakarta.validation.constraints.Positive; + +public record RequestCartItemDto(@Positive Long bookId, + @Positive Integer quantity) { +} diff --git a/src/main/java/com/example/springbootbookshop/dto/cart/item/UpdateRequestCartItemDto.java b/src/main/java/com/example/springbootbookshop/dto/cart/item/UpdateRequestCartItemDto.java new file mode 100644 index 0000000..16bee18 --- /dev/null +++ b/src/main/java/com/example/springbootbookshop/dto/cart/item/UpdateRequestCartItemDto.java @@ -0,0 +1,7 @@ +package com.example.springbootbookshop.dto.cart.item; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Positive; + +public record UpdateRequestCartItemDto(@Positive @NotBlank Integer quantity) { +} diff --git a/src/main/java/com/example/springbootbookshop/entity/Book.java b/src/main/java/com/example/springbootbookshop/entity/Book.java index 1030e11..897dcf5 100644 --- a/src/main/java/com/example/springbootbookshop/entity/Book.java +++ b/src/main/java/com/example/springbootbookshop/entity/Book.java @@ -1,5 +1,6 @@ package com.example.springbootbookshop.entity; +import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -8,9 +9,12 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.JoinTable; import jakarta.persistence.ManyToMany; +import jakarta.persistence.OneToMany; import jakarta.persistence.Table; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; import lombok.Data; import lombok.EqualsAndHashCode; @@ -49,4 +53,7 @@ public class Book { @ToString.Exclude @EqualsAndHashCode.Exclude private Set categories = new HashSet<>(); + + @OneToMany(mappedBy = "book",orphanRemoval = true, cascade = CascadeType.REMOVE) + private List cartItems = new ArrayList<>(); } diff --git a/src/main/java/com/example/springbootbookshop/entity/Cart.java b/src/main/java/com/example/springbootbookshop/entity/Cart.java index cd4beb8..56d0539 100644 --- a/src/main/java/com/example/springbootbookshop/entity/Cart.java +++ b/src/main/java/com/example/springbootbookshop/entity/Cart.java @@ -1,6 +1,5 @@ package com.example.springbootbookshop.entity; -import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -12,6 +11,8 @@ import jakarta.persistence.Table; import java.util.Set; import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; @@ -26,10 +27,12 @@ public class Cart { private Long id; @OneToOne + @ToString.Exclude + @EqualsAndHashCode.Exclude @JoinColumn(name = "user_id", nullable = false) private User user; - @OneToMany(mappedBy = "cart",cascade = CascadeType.REMOVE) + @OneToMany(mappedBy = "cart") private Set cartItems; @Column(nullable = false) diff --git a/src/main/java/com/example/springbootbookshop/entity/CartItem.java b/src/main/java/com/example/springbootbookshop/entity/CartItem.java index 8eba2cc..daeae19 100644 --- a/src/main/java/com/example/springbootbookshop/entity/CartItem.java +++ b/src/main/java/com/example/springbootbookshop/entity/CartItem.java @@ -10,6 +10,8 @@ import jakarta.persistence.Table; import jakarta.validation.constraints.NotNull; import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; @Entity @Data @@ -19,11 +21,13 @@ public class CartItem { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne + @ManyToOne(optional = false) + @ToString.Exclude + @EqualsAndHashCode.Exclude @JoinColumn(name = "cart_id", nullable = false) private Cart cart; - @ManyToOne + @ManyToOne(optional = false) @JoinColumn(name = "book_id", nullable = false) private Book book; diff --git a/src/main/java/com/example/springbootbookshop/entity/User.java b/src/main/java/com/example/springbootbookshop/entity/User.java index 316e4e5..dd0b251 100644 --- a/src/main/java/com/example/springbootbookshop/entity/User.java +++ b/src/main/java/com/example/springbootbookshop/entity/User.java @@ -1,6 +1,5 @@ package com.example.springbootbookshop.entity; -import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -9,7 +8,6 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.JoinTable; import jakarta.persistence.ManyToMany; -import jakarta.persistence.OneToOne; import jakarta.persistence.Table; import java.util.Collection; import java.util.HashSet; @@ -53,9 +51,6 @@ public class User implements UserDetails { @Column(nullable = false) private boolean isDeleted = false; - @OneToOne(mappedBy = "user",cascade = CascadeType.REMOVE) - private Cart cart; - @Override public Collection getAuthorities() { return roles; diff --git a/src/main/java/com/example/springbootbookshop/mapper/CartItemMapper.java b/src/main/java/com/example/springbootbookshop/mapper/CartItemMapper.java new file mode 100644 index 0000000..bada316 --- /dev/null +++ b/src/main/java/com/example/springbootbookshop/mapper/CartItemMapper.java @@ -0,0 +1,21 @@ +package com.example.springbootbookshop.mapper; + +import com.example.springbootbookshop.dto.cart.item.CartItemDto; +import com.example.springbootbookshop.dto.cart.item.RequestCartItemDto; +import com.example.springbootbookshop.entity.CartItem; +import org.mapstruct.InjectionStrategy; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.NullValueCheckStrategy; + +@Mapper(componentModel = "spring", + injectionStrategy = InjectionStrategy.CONSTRUCTOR, + nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, + implementationPackage = ".impl") +public interface CartItemMapper { + @Mapping(source = "book.id", target = "bookId") + @Mapping(source = "book.title", target = "bookTitle") + CartItemDto toDto(CartItem cartItem); + + CartItem toEntity(RequestCartItemDto cartItemDto); +} diff --git a/src/main/java/com/example/springbootbookshop/mapper/CartMapper.java b/src/main/java/com/example/springbootbookshop/mapper/CartMapper.java new file mode 100644 index 0000000..ad84bf8 --- /dev/null +++ b/src/main/java/com/example/springbootbookshop/mapper/CartMapper.java @@ -0,0 +1,23 @@ +package com.example.springbootbookshop.mapper; + +import com.example.springbootbookshop.dto.cart.CartDto; +import com.example.springbootbookshop.dto.cart.item.RequestCartItemDto; +import com.example.springbootbookshop.entity.Cart; +import org.mapstruct.InjectionStrategy; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.NullValueCheckStrategy; + +@Mapper(componentModel = "spring", + injectionStrategy = InjectionStrategy.CONSTRUCTOR, + nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, + implementationPackage = ".impl", + uses = CartItemMapper.class +) +public interface CartMapper { + @Mapping(source = "user.id", target = "userId") + CartDto toDto(Cart cart); + + Cart toEntity(RequestCartItemDto cart); + +} diff --git a/src/main/java/com/example/springbootbookshop/repository/CartItemsRepository.java b/src/main/java/com/example/springbootbookshop/repository/CartItemsRepository.java new file mode 100644 index 0000000..cf992f7 --- /dev/null +++ b/src/main/java/com/example/springbootbookshop/repository/CartItemsRepository.java @@ -0,0 +1,15 @@ +package com.example.springbootbookshop.repository; + +import com.example.springbootbookshop.entity.Book; +import com.example.springbootbookshop.entity.Cart; +import com.example.springbootbookshop.entity.CartItem; +import java.util.Optional; +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CartItemsRepository extends JpaRepository { + @EntityGraph(attributePaths = "book") + Optional findByCartAndBook(Cart cart, Book book); +} diff --git a/src/main/java/com/example/springbootbookshop/repository/CartRepository.java b/src/main/java/com/example/springbootbookshop/repository/CartRepository.java new file mode 100644 index 0000000..f66c5d2 --- /dev/null +++ b/src/main/java/com/example/springbootbookshop/repository/CartRepository.java @@ -0,0 +1,14 @@ +package com.example.springbootbookshop.repository; + +import com.example.springbootbookshop.entity.Cart; +import java.util.Optional; +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CartRepository extends JpaRepository { + @EntityGraph(attributePaths = {"user","cartItems"}) + Optional getCartByUserId(Long id); +} + diff --git a/src/main/java/com/example/springbootbookshop/service/CartService.java b/src/main/java/com/example/springbootbookshop/service/CartService.java new file mode 100644 index 0000000..378a6d1 --- /dev/null +++ b/src/main/java/com/example/springbootbookshop/service/CartService.java @@ -0,0 +1,16 @@ +package com.example.springbootbookshop.service; + +import com.example.springbootbookshop.dto.cart.CartDto; +import com.example.springbootbookshop.dto.cart.item.CartItemDto; +import com.example.springbootbookshop.dto.cart.item.RequestCartItemDto; +import com.example.springbootbookshop.dto.cart.item.UpdateRequestCartItemDto; + +public interface CartService { + CartDto findById(Long id); + + CartItemDto addItemToCart(Long id, RequestCartItemDto requestCartItemDto); + + void removeItem(Long itemId); + + CartItemDto updateCartItem(Long id, UpdateRequestCartItemDto quantity); +} diff --git a/src/main/java/com/example/springbootbookshop/service/impl/CartServiceImpl.java b/src/main/java/com/example/springbootbookshop/service/impl/CartServiceImpl.java new file mode 100644 index 0000000..130d516 --- /dev/null +++ b/src/main/java/com/example/springbootbookshop/service/impl/CartServiceImpl.java @@ -0,0 +1,78 @@ +package com.example.springbootbookshop.service.impl; + +import com.example.springbootbookshop.dto.cart.CartDto; +import com.example.springbootbookshop.dto.cart.item.CartItemDto; +import com.example.springbootbookshop.dto.cart.item.RequestCartItemDto; +import com.example.springbootbookshop.dto.cart.item.UpdateRequestCartItemDto; +import com.example.springbootbookshop.entity.Book; +import com.example.springbootbookshop.entity.Cart; +import com.example.springbootbookshop.entity.CartItem; +import com.example.springbootbookshop.exception.EntityNotFoundException; +import com.example.springbootbookshop.mapper.CartItemMapper; +import com.example.springbootbookshop.mapper.CartMapper; +import com.example.springbootbookshop.repository.BookRepository; +import com.example.springbootbookshop.repository.CartItemsRepository; +import com.example.springbootbookshop.repository.CartRepository; +import com.example.springbootbookshop.repository.UserRepository; +import com.example.springbootbookshop.service.CartService; +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class CartServiceImpl implements CartService { + private final CartRepository cartRepository; + private final CartMapper cartMapper; + private final BookRepository bookRepository; + private final UserRepository userRepository; + private final CartItemMapper cartItemMapper; + private final CartItemsRepository cartItemsRepository; + + @Override + public CartDto findById(Long id) { + Cart cart = cartRepository.getCartByUserId(id).orElseThrow( + () -> new EntityNotFoundException("User with id " + + id + "don`t have a cart") + ); + return cartMapper.toDto(cart); + } + + @Override + public CartItemDto addItemToCart(Long userId, RequestCartItemDto requestCartItemDto) { + Cart cart = cartRepository.getCartByUserId(userId).get(); + Book book = bookRepository.findById(requestCartItemDto.bookId()).orElseThrow( + () -> new EntityNotFoundException("Book with id: " + requestCartItemDto.bookId() + + "doesn`t exist")); + int quantityToAdd = requestCartItemDto.quantity(); + Optional existingCartItem = cartItemsRepository.findByCartAndBook(cart, book); + if (existingCartItem.isPresent()) { + existingCartItem.get().setQuantity(existingCartItem.get() + .getQuantity() + quantityToAdd); + cartItemsRepository.save(existingCartItem.get()); + return cartItemMapper.toDto(existingCartItem.get()); + } + CartItem entity = cartItemMapper.toEntity(requestCartItemDto); + entity.setBook(book); + entity.setCart(cart); + return cartItemMapper.toDto(cartItemsRepository.save(entity)); + } + + @Override + public void removeItem(Long itemId) { + if (!cartItemsRepository.existsById(itemId)) { + throw new EntityNotFoundException("Item with id: " + itemId + + " doesn`t exist"); + } + cartItemsRepository.deleteById(itemId); + } + + @Override + public CartItemDto updateCartItem(Long id, UpdateRequestCartItemDto quantity) { + CartItem cartItemToUpdate = cartItemsRepository.findById(id).orElseThrow( + () -> new EntityNotFoundException("Nothing to update, item with id: " + + id + " doesn`t exist")); + cartItemToUpdate.setQuantity(quantity.quantity()); + return cartItemMapper.toDto(cartItemsRepository.save(cartItemToUpdate)); + } +} diff --git a/src/main/java/com/example/springbootbookshop/service/impl/CategoryServiceImpl.java b/src/main/java/com/example/springbootbookshop/service/impl/CategoryServiceImpl.java index cacc592..357b7ef 100644 --- a/src/main/java/com/example/springbootbookshop/service/impl/CategoryServiceImpl.java +++ b/src/main/java/com/example/springbootbookshop/service/impl/CategoryServiceImpl.java @@ -50,8 +50,8 @@ public CategoryDto update(Long id, CategoryRequestDto categoryRequestDtoDto) { @Override public void deleteById(Long id) { if (!categoryRepository.existsById(id)) { - throw new EntityNotFoundException("Category with id " + id - + "doesn`t exist"); + throw new EntityNotFoundException("Category with id: " + id + + " doesn`t exist"); } categoryRepository.deleteById(id); } diff --git a/src/main/java/com/example/springbootbookshop/service/impl/UserServiceImpl.java b/src/main/java/com/example/springbootbookshop/service/impl/UserServiceImpl.java index 691fea6..81d0795 100644 --- a/src/main/java/com/example/springbootbookshop/service/impl/UserServiceImpl.java +++ b/src/main/java/com/example/springbootbookshop/service/impl/UserServiceImpl.java @@ -2,11 +2,13 @@ import com.example.springbootbookshop.dto.user.UserRegistrationRequestDto; import com.example.springbootbookshop.dto.user.UserResponseDto; +import com.example.springbootbookshop.entity.Cart; import com.example.springbootbookshop.entity.Role; import com.example.springbootbookshop.entity.RoleName; import com.example.springbootbookshop.entity.User; import com.example.springbootbookshop.exception.RegistrationException; import com.example.springbootbookshop.mapper.UserMapper; +import com.example.springbootbookshop.repository.CartRepository; import com.example.springbootbookshop.repository.RoleRepository; import com.example.springbootbookshop.repository.UserRepository; import com.example.springbootbookshop.service.UserService; @@ -22,6 +24,7 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; private final RoleRepository roleRepository; + private final CartRepository cartRepository; private final UserMapper userMapper; private final PasswordEncoder passwordEncoder; @@ -35,7 +38,15 @@ public UserResponseDto register(UserRegistrationRequestDto requestDto) User user = userMapper.toUserModel(requestDto); user.setPassword(passwordEncoder.encode(requestDto.password())); user.setRoles(getUserRole()); - return userMapper.toUserDto(userRepository.save(user)); + User savedUser = userRepository.save(user); + createAndSetNewCartToUser(savedUser); + return userMapper.toUserDto(savedUser); + } + + private void createAndSetNewCartToUser(User user) { + Cart cart = new Cart(); + cart.setUser(user); + cartRepository.save(cart); } private Set getUserRole() { diff --git a/src/main/resources/db/changelog/changes/07-create-carts-table.yaml b/src/main/resources/db/changelog/changes/07-create-carts-table.yaml index fd2224c..4e8ba3c 100644 --- a/src/main/resources/db/changelog/changes/07-create-carts-table.yaml +++ b/src/main/resources/db/changelog/changes/07-create-carts-table.yaml @@ -9,10 +9,10 @@ databaseChangeLog: - column: name: id type: BIGINT + autoIncrement: true constraints: primaryKey: true nullable: false - autoIncrement: true - column: name: user_id type: BIGINT @@ -21,9 +21,9 @@ databaseChangeLog: - column: name: is_deleted type: BOOLEAN + defaultValueBoolean: false constraints: nullable: false - defaultValueBoolean: false - addForeignKeyConstraint: baseTableName: carts baseColumnNames: user_id diff --git a/src/main/resources/db/changelog/changes/08-create-cart-items-table.yaml b/src/main/resources/db/changelog/changes/08-create-cart-items-table.yaml index 1cebb1d..c8b9ddf 100644 --- a/src/main/resources/db/changelog/changes/08-create-cart-items-table.yaml +++ b/src/main/resources/db/changelog/changes/08-create-cart-items-table.yaml @@ -9,10 +9,10 @@ databaseChangeLog: - column: name: id type: BIGINT + autoIncrement: true constraints: primaryKey: true nullable: false - autoIncrement: true - column: name: cart_id type: BIGINT @@ -27,17 +27,4 @@ databaseChangeLog: name: quantity type: INTEGER constraints: - nullable: false - - addForeignKeyConstraint: - baseTableName: cart_items - baseColumnNames: cart_id - referencedTableName: carts - referencedColumnNames: id - constraintName: FK_cart_items_cart - onDelete: CASCADE - - addForeignKeyConstraint: - baseTableName: cart_items - baseColumnNames: book_id - referencedTableName: books - referencedColumnNames: id - constraintName: FK_cart_items_book + nullable: false \ No newline at end of file From 003c992f6942383cac19b084d27bdc07442dd9d5 Mon Sep 17 00:00:00 2001 From: Bogdan <97698639+don-bigdad@users.noreply.github.com> Date: Mon, 13 Nov 2023 16:31:39 +0200 Subject: [PATCH 4/5] upgrade addItemToCart logic and some minor checkstyle fixes --- .../controller/BookController.java | 8 +++--- .../controller/CartController.java | 11 ++++---- .../cart/item/UpdateRequestCartItemDto.java | 3 +-- .../springbootbookshop/entity/Cart.java | 6 +++-- .../springbootbookshop/entity/CartItem.java | 5 ++-- .../springbootbookshop/mapper/CartMapper.java | 1 - .../repository/CartRepository.java | 1 - .../service/impl/CartServiceImpl.java | 26 +++++++++---------- .../service/impl/UserServiceImpl.java | 7 +++-- 9 files changed, 32 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/example/springbootbookshop/controller/BookController.java b/src/main/java/com/example/springbootbookshop/controller/BookController.java index 920dcfe..46d665e 100644 --- a/src/main/java/com/example/springbootbookshop/controller/BookController.java +++ b/src/main/java/com/example/springbootbookshop/controller/BookController.java @@ -28,7 +28,7 @@ @Tag(name = "Book management",description = "Endpoints for managing books") @RestController @Validated -@RequestMapping(value = "/books") +@RequestMapping("/books") public class BookController { private final BookService bookService; @@ -41,7 +41,7 @@ public List getAll(@PageableDefault(size = 5, page = 0) return bookService.findAll(pageable); } - @DeleteMapping(value = "/{id}") + @DeleteMapping("/{id}") @PreAuthorize("hasRole('ADMIN')") @Operation(summary = "Delete book by id") @ResponseStatus(HttpStatus.NO_CONTENT) @@ -49,7 +49,7 @@ public void deleteBookById(@PathVariable @Positive Long id) { bookService.deleteById(id); } - @GetMapping(value = "/{id}") + @GetMapping("/{id}") @Operation(summary = "Get book by Id from DB") @PreAuthorize("hasRole('USER')") @ResponseStatus(HttpStatus.OK) @@ -57,7 +57,7 @@ public BookDto getBookById(@PathVariable @Positive Long id) { return bookService.getBookById(id); } - @PutMapping(value = "/{id}") + @PutMapping("/{id}") @PreAuthorize("hasRole('ADMIN')") @Operation(summary = "Update book by Id in DB") @ResponseStatus(HttpStatus.OK) diff --git a/src/main/java/com/example/springbootbookshop/controller/CartController.java b/src/main/java/com/example/springbootbookshop/controller/CartController.java index b17d46e..ab49a13 100644 --- a/src/main/java/com/example/springbootbookshop/controller/CartController.java +++ b/src/main/java/com/example/springbootbookshop/controller/CartController.java @@ -29,7 +29,7 @@ @Tag(name = "Cart management",description = "Endpoints for managing carts") @RestController @Validated -@RequestMapping(value = "/cart") +@RequestMapping("/cart") public class CartController { private final CartService cartService; @@ -48,21 +48,20 @@ public CartItemDto addItemToCart(Authentication authentication, return cartService.addItemToCart(getUserId(authentication), cartItem); } - @DeleteMapping(value = "cart-items/{id}") + @DeleteMapping("cart-items/{id}") @Operation(summary = "Delete cart item from the user cart") @PreAuthorize("hasRole('USER')") @ResponseStatus(HttpStatus.NO_CONTENT) - public void removeCartItem(Authentication authentication, - @PathVariable @Positive Long id) { + public void removeCartItem(@PathVariable @Positive Long id) { cartService.removeItem(id); } - @PutMapping(value = "cart-items/{id}") + @PutMapping("cart-items/{id}") @Operation(summary = "Update cart item in the user cart") @PreAuthorize("hasRole('USER')") @ResponseStatus(HttpStatus.OK) public CartItemDto updateItemQuantity(@PathVariable @Positive Long id, - @RequestBody UpdateRequestCartItemDto quantity) { + @RequestBody @Valid UpdateRequestCartItemDto quantity) { return cartService.updateCartItem(id, quantity); } diff --git a/src/main/java/com/example/springbootbookshop/dto/cart/item/UpdateRequestCartItemDto.java b/src/main/java/com/example/springbootbookshop/dto/cart/item/UpdateRequestCartItemDto.java index 16bee18..274ea6f 100644 --- a/src/main/java/com/example/springbootbookshop/dto/cart/item/UpdateRequestCartItemDto.java +++ b/src/main/java/com/example/springbootbookshop/dto/cart/item/UpdateRequestCartItemDto.java @@ -1,7 +1,6 @@ package com.example.springbootbookshop.dto.cart.item; -import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Positive; -public record UpdateRequestCartItemDto(@Positive @NotBlank Integer quantity) { +public record UpdateRequestCartItemDto(@Positive Integer quantity) { } diff --git a/src/main/java/com/example/springbootbookshop/entity/Cart.java b/src/main/java/com/example/springbootbookshop/entity/Cart.java index 56d0539..6c3fafe 100644 --- a/src/main/java/com/example/springbootbookshop/entity/Cart.java +++ b/src/main/java/com/example/springbootbookshop/entity/Cart.java @@ -2,6 +2,7 @@ import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; @@ -9,6 +10,7 @@ import jakarta.persistence.OneToMany; import jakarta.persistence.OneToOne; import jakarta.persistence.Table; +import java.util.HashSet; import java.util.Set; import lombok.Data; import lombok.EqualsAndHashCode; @@ -26,14 +28,14 @@ public class Cart { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @OneToOne + @OneToOne(fetch = FetchType.LAZY, optional = false) @ToString.Exclude @EqualsAndHashCode.Exclude @JoinColumn(name = "user_id", nullable = false) private User user; @OneToMany(mappedBy = "cart") - private Set cartItems; + private Set cartItems = new HashSet<>(); @Column(nullable = false) private boolean isDeleted = false; diff --git a/src/main/java/com/example/springbootbookshop/entity/CartItem.java b/src/main/java/com/example/springbootbookshop/entity/CartItem.java index daeae19..1b7360f 100644 --- a/src/main/java/com/example/springbootbookshop/entity/CartItem.java +++ b/src/main/java/com/example/springbootbookshop/entity/CartItem.java @@ -2,6 +2,7 @@ import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; @@ -21,13 +22,13 @@ public class CartItem { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(optional = false) + @ManyToOne(fetch = FetchType.LAZY, optional = false) @ToString.Exclude @EqualsAndHashCode.Exclude @JoinColumn(name = "cart_id", nullable = false) private Cart cart; - @ManyToOne(optional = false) + @ManyToOne(fetch = FetchType.LAZY, optional = false) @JoinColumn(name = "book_id", nullable = false) private Book book; diff --git a/src/main/java/com/example/springbootbookshop/mapper/CartMapper.java b/src/main/java/com/example/springbootbookshop/mapper/CartMapper.java index ad84bf8..e45fc9c 100644 --- a/src/main/java/com/example/springbootbookshop/mapper/CartMapper.java +++ b/src/main/java/com/example/springbootbookshop/mapper/CartMapper.java @@ -19,5 +19,4 @@ public interface CartMapper { CartDto toDto(Cart cart); Cart toEntity(RequestCartItemDto cart); - } diff --git a/src/main/java/com/example/springbootbookshop/repository/CartRepository.java b/src/main/java/com/example/springbootbookshop/repository/CartRepository.java index f66c5d2..8ae3ed4 100644 --- a/src/main/java/com/example/springbootbookshop/repository/CartRepository.java +++ b/src/main/java/com/example/springbootbookshop/repository/CartRepository.java @@ -11,4 +11,3 @@ public interface CartRepository extends JpaRepository { @EntityGraph(attributePaths = {"user","cartItems"}) Optional getCartByUserId(Long id); } - diff --git a/src/main/java/com/example/springbootbookshop/service/impl/CartServiceImpl.java b/src/main/java/com/example/springbootbookshop/service/impl/CartServiceImpl.java index 130d516..665cdda 100644 --- a/src/main/java/com/example/springbootbookshop/service/impl/CartServiceImpl.java +++ b/src/main/java/com/example/springbootbookshop/service/impl/CartServiceImpl.java @@ -13,11 +13,10 @@ import com.example.springbootbookshop.repository.BookRepository; import com.example.springbootbookshop.repository.CartItemsRepository; import com.example.springbootbookshop.repository.CartRepository; -import com.example.springbootbookshop.repository.UserRepository; import com.example.springbootbookshop.service.CartService; -import java.util.Optional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor @@ -25,10 +24,10 @@ public class CartServiceImpl implements CartService { private final CartRepository cartRepository; private final CartMapper cartMapper; private final BookRepository bookRepository; - private final UserRepository userRepository; private final CartItemMapper cartItemMapper; private final CartItemsRepository cartItemsRepository; + @Transactional(readOnly = true) @Override public CartDto findById(Long id) { Cart cart = cartRepository.getCartByUserId(id).orElseThrow( @@ -39,23 +38,22 @@ public CartDto findById(Long id) { } @Override + @Transactional public CartItemDto addItemToCart(Long userId, RequestCartItemDto requestCartItemDto) { Cart cart = cartRepository.getCartByUserId(userId).get(); Book book = bookRepository.findById(requestCartItemDto.bookId()).orElseThrow( () -> new EntityNotFoundException("Book with id: " + requestCartItemDto.bookId() + "doesn`t exist")); int quantityToAdd = requestCartItemDto.quantity(); - Optional existingCartItem = cartItemsRepository.findByCartAndBook(cart, book); - if (existingCartItem.isPresent()) { - existingCartItem.get().setQuantity(existingCartItem.get() - .getQuantity() + quantityToAdd); - cartItemsRepository.save(existingCartItem.get()); - return cartItemMapper.toDto(existingCartItem.get()); - } - CartItem entity = cartItemMapper.toEntity(requestCartItemDto); - entity.setBook(book); - entity.setCart(cart); - return cartItemMapper.toDto(cartItemsRepository.save(entity)); + CartItem cartItem = cartItemsRepository.findByCartAndBook(cart, book) + .orElseGet(() -> { + CartItem newCartItem = cartItemMapper.toEntity(requestCartItemDto); + newCartItem.setBook(book); + newCartItem.setCart(cart); + return newCartItem; + }); + cartItem.setQuantity(quantityToAdd + cartItem.getQuantity()); + return cartItemMapper.toDto(cartItemsRepository.save(cartItem)); } @Override diff --git a/src/main/java/com/example/springbootbookshop/service/impl/UserServiceImpl.java b/src/main/java/com/example/springbootbookshop/service/impl/UserServiceImpl.java index 81d0795..b089480 100644 --- a/src/main/java/com/example/springbootbookshop/service/impl/UserServiceImpl.java +++ b/src/main/java/com/example/springbootbookshop/service/impl/UserServiceImpl.java @@ -38,12 +38,11 @@ public UserResponseDto register(UserRegistrationRequestDto requestDto) User user = userMapper.toUserModel(requestDto); user.setPassword(passwordEncoder.encode(requestDto.password())); user.setRoles(getUserRole()); - User savedUser = userRepository.save(user); - createAndSetNewCartToUser(savedUser); - return userMapper.toUserDto(savedUser); + setShoppingCartForUser(userRepository.save(user)); + return userMapper.toUserDto(user); } - private void createAndSetNewCartToUser(User user) { + private void setShoppingCartForUser(User user) { Cart cart = new Cart(); cart.setUser(user); cartRepository.save(cart); From e45d401eb874c74e9343c08f0f049d8b456771a3 Mon Sep 17 00:00:00 2001 From: Bogdan <97698639+don-bigdad@users.noreply.github.com> Date: Tue, 14 Nov 2023 18:17:57 +0200 Subject: [PATCH 5/5] upgrade logic for delete cart item.Now another user with another cart can`t delete cartItem in another users cart --- .../controller/CartController.java | 5 +++-- .../repository/CartItemsRepository.java | 2 ++ .../springbootbookshop/service/CartService.java | 2 +- .../service/impl/CartServiceImpl.java | 14 +++++++++----- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/example/springbootbookshop/controller/CartController.java b/src/main/java/com/example/springbootbookshop/controller/CartController.java index ab49a13..4e22c87 100644 --- a/src/main/java/com/example/springbootbookshop/controller/CartController.java +++ b/src/main/java/com/example/springbootbookshop/controller/CartController.java @@ -52,8 +52,9 @@ public CartItemDto addItemToCart(Authentication authentication, @Operation(summary = "Delete cart item from the user cart") @PreAuthorize("hasRole('USER')") @ResponseStatus(HttpStatus.NO_CONTENT) - public void removeCartItem(@PathVariable @Positive Long id) { - cartService.removeItem(id); + public void removeCartItem(Authentication authentication, + @PathVariable @Positive Long id) { + cartService.removeItem(getUserId(authentication), id); } @PutMapping("cart-items/{id}") diff --git a/src/main/java/com/example/springbootbookshop/repository/CartItemsRepository.java b/src/main/java/com/example/springbootbookshop/repository/CartItemsRepository.java index cf992f7..e3c9460 100644 --- a/src/main/java/com/example/springbootbookshop/repository/CartItemsRepository.java +++ b/src/main/java/com/example/springbootbookshop/repository/CartItemsRepository.java @@ -12,4 +12,6 @@ public interface CartItemsRepository extends JpaRepository { @EntityGraph(attributePaths = "book") Optional findByCartAndBook(Cart cart, Book book); + + Optional getCartItemsByIdAndCartId(Long itemId,Long cartId); } diff --git a/src/main/java/com/example/springbootbookshop/service/CartService.java b/src/main/java/com/example/springbootbookshop/service/CartService.java index 378a6d1..e0b8b05 100644 --- a/src/main/java/com/example/springbootbookshop/service/CartService.java +++ b/src/main/java/com/example/springbootbookshop/service/CartService.java @@ -10,7 +10,7 @@ public interface CartService { CartItemDto addItemToCart(Long id, RequestCartItemDto requestCartItemDto); - void removeItem(Long itemId); + void removeItem(Long userId, Long itemId); CartItemDto updateCartItem(Long id, UpdateRequestCartItemDto quantity); } diff --git a/src/main/java/com/example/springbootbookshop/service/impl/CartServiceImpl.java b/src/main/java/com/example/springbootbookshop/service/impl/CartServiceImpl.java index 665cdda..7ed7888 100644 --- a/src/main/java/com/example/springbootbookshop/service/impl/CartServiceImpl.java +++ b/src/main/java/com/example/springbootbookshop/service/impl/CartServiceImpl.java @@ -57,11 +57,15 @@ public CartItemDto addItemToCart(Long userId, RequestCartItemDto requestCartItem } @Override - public void removeItem(Long itemId) { - if (!cartItemsRepository.existsById(itemId)) { - throw new EntityNotFoundException("Item with id: " + itemId - + " doesn`t exist"); - } + @Transactional + public void removeItem(Long userId, Long itemId) { + Cart cart = cartRepository.getCartByUserId(userId) + .orElseThrow(() -> new EntityNotFoundException( + "Shopping cart not found for user with id: " + userId)); + CartItem cartItem = cartItemsRepository.getCartItemsByIdAndCartId(itemId, + cart.getId()) + .orElseThrow(() -> new EntityNotFoundException( + "Cart item not found in the user's shopping cart")); cartItemsRepository.deleteById(itemId); }