From 2c9e448a0886f45d168273493e39ae7d5276c7b4 Mon Sep 17 00:00:00 2001 From: Tetiana Date: Thu, 12 Oct 2023 14:04:10 +0300 Subject: [PATCH 1/2] added order functionality --- .../bookstore/controller/OrderController.java | 67 +++++++++++ .../bookstore/dto/order/OrderItemDto.java | 10 ++ .../bookstore/dto/order/OrderRequestDto.java | 11 ++ .../bookstore/dto/order/OrderResponseDto.java | 16 +++ .../dto/order/OrderUpdateRequestDto.java | 8 ++ .../bookstore/mapper/OrderItemMapper.java | 16 +++ .../vozniuk/bookstore/mapper/OrderMapper.java | 16 +++ .../com/vozniuk/bookstore/model/Order.java | 59 ++++++++++ .../vozniuk/bookstore/model/OrderItem.java | 44 ++++++++ .../repository/OrderItemRepository.java | 15 +++ .../bookstore/repository/OrderRepository.java | 7 ++ .../bookstore/service/OrderService.java | 20 ++++ .../service/impl/OrderServiceImpl.java | 106 ++++++++++++++++++ .../changes/12-create-statuses-table.yaml | 21 ++++ .../changes/13-fill-statuses-table.yaml | 25 +++++ .../changes/14-create-orders-table.yaml | 49 ++++++++ .../changes/15-create-order_items-table.yaml | 47 ++++++++ .../db/changelog/db.changelog-master.yaml | 10 +- 18 files changed, 546 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/vozniuk/bookstore/controller/OrderController.java create mode 100644 src/main/java/com/vozniuk/bookstore/dto/order/OrderItemDto.java create mode 100644 src/main/java/com/vozniuk/bookstore/dto/order/OrderRequestDto.java create mode 100644 src/main/java/com/vozniuk/bookstore/dto/order/OrderResponseDto.java create mode 100644 src/main/java/com/vozniuk/bookstore/dto/order/OrderUpdateRequestDto.java create mode 100644 src/main/java/com/vozniuk/bookstore/mapper/OrderItemMapper.java create mode 100644 src/main/java/com/vozniuk/bookstore/mapper/OrderMapper.java create mode 100644 src/main/java/com/vozniuk/bookstore/model/Order.java create mode 100644 src/main/java/com/vozniuk/bookstore/model/OrderItem.java create mode 100644 src/main/java/com/vozniuk/bookstore/repository/OrderItemRepository.java create mode 100644 src/main/java/com/vozniuk/bookstore/repository/OrderRepository.java create mode 100644 src/main/java/com/vozniuk/bookstore/service/OrderService.java create mode 100644 src/main/java/com/vozniuk/bookstore/service/impl/OrderServiceImpl.java create mode 100644 src/main/resources/db/changelog/changes/12-create-statuses-table.yaml create mode 100644 src/main/resources/db/changelog/changes/13-fill-statuses-table.yaml create mode 100644 src/main/resources/db/changelog/changes/14-create-orders-table.yaml create mode 100644 src/main/resources/db/changelog/changes/15-create-order_items-table.yaml diff --git a/src/main/java/com/vozniuk/bookstore/controller/OrderController.java b/src/main/java/com/vozniuk/bookstore/controller/OrderController.java new file mode 100644 index 0000000..f9ab6fb --- /dev/null +++ b/src/main/java/com/vozniuk/bookstore/controller/OrderController.java @@ -0,0 +1,67 @@ +package com.vozniuk.bookstore.controller; + +import com.vozniuk.bookstore.dto.order.OrderItemDto; +import com.vozniuk.bookstore.dto.order.OrderRequestDto; +import com.vozniuk.bookstore.dto.order.OrderResponseDto; +import com.vozniuk.bookstore.dto.order.OrderUpdateRequestDto; +import com.vozniuk.bookstore.service.OrderService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "Order management", description = "Endpoints for managing orders") +@RequiredArgsConstructor +@RestController +@RequestMapping(value = "/api/orders") +public class OrderController { + private final OrderService orderService; + + @PostMapping + @Operation(summary = "Place an order", + description = "Place an order") + public OrderResponseDto placeOrder(@RequestBody @Valid OrderRequestDto requestDto) { + return orderService.save(requestDto); + } + + @GetMapping + @Operation(summary = "Get all orders", + description = "Get a list of all orders made by user") + public List getAllOrders(Pageable pageable) { + return orderService.findAll(pageable); + } + + @PreAuthorize("hasRole('ROLE_ADMIN')") + @PatchMapping("/{id}") + @Operation(summary = "Update order status", + description = "Update order status") + public OrderResponseDto updateOrderStatus( + @PathVariable Long id, + @RequestBody @Valid OrderUpdateRequestDto requestDto) { + return orderService.updateOrderStatus(id, requestDto); + } + + @GetMapping("/{orderId}/items") + @Operation(summary = "Get all order items", + description = "Get a list of all items in the order") + public List getAllOrderItems(@PathVariable Long orderId, Pageable pageable) { + return orderService.findAllOrderItems(orderId, pageable); + } + + @GetMapping("{orderId}/items/{itemId}") + @Operation(summary = "Get order item by id", + description = "Get order item by order id") + public OrderItemDto getAllOrderItems(@PathVariable Long orderId, @PathVariable Long itemId) { + return orderService.findOrderItemById(orderId, itemId); + } +} diff --git a/src/main/java/com/vozniuk/bookstore/dto/order/OrderItemDto.java b/src/main/java/com/vozniuk/bookstore/dto/order/OrderItemDto.java new file mode 100644 index 0000000..92ad52d --- /dev/null +++ b/src/main/java/com/vozniuk/bookstore/dto/order/OrderItemDto.java @@ -0,0 +1,10 @@ +package com.vozniuk.bookstore.dto.order; + +import lombok.Data; + +@Data +public class OrderItemDto { + private Long id; + private Long bookId; + private int quantity; +} diff --git a/src/main/java/com/vozniuk/bookstore/dto/order/OrderRequestDto.java b/src/main/java/com/vozniuk/bookstore/dto/order/OrderRequestDto.java new file mode 100644 index 0000000..7e1dbb6 --- /dev/null +++ b/src/main/java/com/vozniuk/bookstore/dto/order/OrderRequestDto.java @@ -0,0 +1,11 @@ +package com.vozniuk.bookstore.dto.order; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class OrderRequestDto { + @NotNull + private String shippingAddress; + +} diff --git a/src/main/java/com/vozniuk/bookstore/dto/order/OrderResponseDto.java b/src/main/java/com/vozniuk/bookstore/dto/order/OrderResponseDto.java new file mode 100644 index 0000000..74ec37c --- /dev/null +++ b/src/main/java/com/vozniuk/bookstore/dto/order/OrderResponseDto.java @@ -0,0 +1,16 @@ +package com.vozniuk.bookstore.dto.order; + +import java.math.BigInteger; +import java.time.LocalDateTime; +import java.util.Set; +import lombok.Data; + +@Data +public class OrderResponseDto { + private Long id; + private Long userId; + private Set orderItems; + private LocalDateTime orderDate; + private BigInteger total; + private String status; +} diff --git a/src/main/java/com/vozniuk/bookstore/dto/order/OrderUpdateRequestDto.java b/src/main/java/com/vozniuk/bookstore/dto/order/OrderUpdateRequestDto.java new file mode 100644 index 0000000..21ec922 --- /dev/null +++ b/src/main/java/com/vozniuk/bookstore/dto/order/OrderUpdateRequestDto.java @@ -0,0 +1,8 @@ +package com.vozniuk.bookstore.dto.order; + +import lombok.Data; + +@Data +public class OrderUpdateRequestDto { + private String status; +} diff --git a/src/main/java/com/vozniuk/bookstore/mapper/OrderItemMapper.java b/src/main/java/com/vozniuk/bookstore/mapper/OrderItemMapper.java new file mode 100644 index 0000000..b97ad86 --- /dev/null +++ b/src/main/java/com/vozniuk/bookstore/mapper/OrderItemMapper.java @@ -0,0 +1,16 @@ +package com.vozniuk.bookstore.mapper; + +import com.vozniuk.bookstore.config.MapperConfig; +import com.vozniuk.bookstore.dto.order.OrderItemDto; +import com.vozniuk.bookstore.model.OrderItem; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +@Mapper(config = MapperConfig.class, uses = BookMapper.class) +public interface OrderItemMapper { + @Mapping(source = "book.id", target = "bookId") + OrderItemDto toDto(OrderItem cartItem); + + @Mapping(target = "book", source = "bookId", qualifiedByName = "bookFromId") + OrderItem toEntity(OrderItemDto orderItemDto); +} diff --git a/src/main/java/com/vozniuk/bookstore/mapper/OrderMapper.java b/src/main/java/com/vozniuk/bookstore/mapper/OrderMapper.java new file mode 100644 index 0000000..2e54729 --- /dev/null +++ b/src/main/java/com/vozniuk/bookstore/mapper/OrderMapper.java @@ -0,0 +1,16 @@ +package com.vozniuk.bookstore.mapper; + +import com.vozniuk.bookstore.config.MapperConfig; +import com.vozniuk.bookstore.dto.order.OrderResponseDto; +import com.vozniuk.bookstore.model.Order; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +@Mapper(config = MapperConfig.class, uses = OrderItemMapper.class) +public interface OrderMapper { + @Mapping(source = "user.id", target = "userId") + OrderResponseDto toDto(Order order); + + @Mapping(source = "userId", target = "user.id") + Order toEntity(OrderResponseDto orderResponseDto); +} diff --git a/src/main/java/com/vozniuk/bookstore/model/Order.java b/src/main/java/com/vozniuk/bookstore/model/Order.java new file mode 100644 index 0000000..2e4d7ce --- /dev/null +++ b/src/main/java/com/vozniuk/bookstore/model/Order.java @@ -0,0 +1,59 @@ +package com.vozniuk.bookstore.model; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.HashSet; +import java.util.Set; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; + +@Entity +@Data +@SQLDelete(sql = "UPDATE orders SET is_deleted = true WHERE id = ?") +@Where(clause = "is_deleted = false") +@Table(name = "orders") +public class Order { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + @ManyToOne + @JoinColumn(name = "user_id") + @ToString.Exclude + @EqualsAndHashCode.Exclude + private User user; + @Enumerated(EnumType.STRING) + @Column(nullable = false, name = "status") + private Status status; + @Column(nullable = false) + private BigDecimal total; + @Column(nullable = false) + private LocalDateTime orderDate; + @Column(nullable = false) + private String shippingAddress; + @OneToMany(mappedBy = "order") + @ToString.Exclude + @EqualsAndHashCode.Exclude + private Set orderItems = new HashSet<>(); + + public enum Status { + NEW, + PROCESSING, + SHIPPED, + COMPLETED, + CANCELLED + } +} diff --git a/src/main/java/com/vozniuk/bookstore/model/OrderItem.java b/src/main/java/com/vozniuk/bookstore/model/OrderItem.java new file mode 100644 index 0000000..4e442a8 --- /dev/null +++ b/src/main/java/com/vozniuk/bookstore/model/OrderItem.java @@ -0,0 +1,44 @@ +package com.vozniuk.bookstore.model; + +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.OneToOne; +import jakarta.persistence.Table; +import java.math.BigDecimal; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; + +@Entity +@Data +@SQLDelete(sql = "UPDATE order_items SET is_deleted = true WHERE id = ?") +@Where(clause = "is_deleted = false") +@Table(name = "order_items") +public class OrderItem { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + @ManyToOne + @JoinColumn(name = "order_id") + @ToString.Exclude + @EqualsAndHashCode.Exclude + private Order order; + @OneToOne + @JoinColumn(name = "book_id") + @ToString.Exclude + @EqualsAndHashCode.Exclude + private Book book; + @Column(nullable = false) + private int quantity; + @Column(nullable = false) + private BigDecimal price; + @Column(nullable = false) + private boolean isDeleted = false; +} diff --git a/src/main/java/com/vozniuk/bookstore/repository/OrderItemRepository.java b/src/main/java/com/vozniuk/bookstore/repository/OrderItemRepository.java new file mode 100644 index 0000000..fb6352d --- /dev/null +++ b/src/main/java/com/vozniuk/bookstore/repository/OrderItemRepository.java @@ -0,0 +1,15 @@ +package com.vozniuk.bookstore.repository; + +import com.vozniuk.bookstore.model.OrderItem; +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface OrderItemRepository extends JpaRepository { + @Query("FROM OrderItem oi " + + "LEFT JOIN FETCH oi.order o " + + "WHERE oi.id = :itemId AND o.id = :orderId") + Optional findByOrderAndItemIds(@Param("orderId")Long orderId, + @Param("itemId") Long itemId); +} diff --git a/src/main/java/com/vozniuk/bookstore/repository/OrderRepository.java b/src/main/java/com/vozniuk/bookstore/repository/OrderRepository.java new file mode 100644 index 0000000..2fe00ee --- /dev/null +++ b/src/main/java/com/vozniuk/bookstore/repository/OrderRepository.java @@ -0,0 +1,7 @@ +package com.vozniuk.bookstore.repository; + +import com.vozniuk.bookstore.model.Order; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface OrderRepository extends JpaRepository { +} diff --git a/src/main/java/com/vozniuk/bookstore/service/OrderService.java b/src/main/java/com/vozniuk/bookstore/service/OrderService.java new file mode 100644 index 0000000..8d3e7f5 --- /dev/null +++ b/src/main/java/com/vozniuk/bookstore/service/OrderService.java @@ -0,0 +1,20 @@ +package com.vozniuk.bookstore.service; + +import com.vozniuk.bookstore.dto.order.OrderItemDto; +import com.vozniuk.bookstore.dto.order.OrderRequestDto; +import com.vozniuk.bookstore.dto.order.OrderResponseDto; +import com.vozniuk.bookstore.dto.order.OrderUpdateRequestDto; +import java.util.List; +import org.springframework.data.domain.Pageable; + +public interface OrderService { + OrderResponseDto save(OrderRequestDto requestDto); + + List findAll(Pageable pageable); + + OrderResponseDto updateOrderStatus(Long id, OrderUpdateRequestDto requestDto); + + List findAllOrderItems(Long orderId, Pageable pageable); + + OrderItemDto findOrderItemById(Long orderId, Long itemId); +} diff --git a/src/main/java/com/vozniuk/bookstore/service/impl/OrderServiceImpl.java b/src/main/java/com/vozniuk/bookstore/service/impl/OrderServiceImpl.java new file mode 100644 index 0000000..ed17b11 --- /dev/null +++ b/src/main/java/com/vozniuk/bookstore/service/impl/OrderServiceImpl.java @@ -0,0 +1,106 @@ +package com.vozniuk.bookstore.service.impl; + +import com.vozniuk.bookstore.dto.order.OrderItemDto; +import com.vozniuk.bookstore.dto.order.OrderRequestDto; +import com.vozniuk.bookstore.dto.order.OrderResponseDto; +import com.vozniuk.bookstore.dto.order.OrderUpdateRequestDto; +import com.vozniuk.bookstore.exception.EntityNotFoundException; +import com.vozniuk.bookstore.mapper.OrderItemMapper; +import com.vozniuk.bookstore.mapper.OrderMapper; +import com.vozniuk.bookstore.model.CartItem; +import com.vozniuk.bookstore.model.Order; +import com.vozniuk.bookstore.model.OrderItem; +import com.vozniuk.bookstore.model.ShoppingCart; +import com.vozniuk.bookstore.repository.OrderItemRepository; +import com.vozniuk.bookstore.repository.OrderRepository; +import com.vozniuk.bookstore.repository.ShoppingCartRepository; +import com.vozniuk.bookstore.repository.UserRepository; +import com.vozniuk.bookstore.security.AuthenticationService; +import com.vozniuk.bookstore.service.OrderService; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class OrderServiceImpl implements OrderService { + private final OrderRepository orderRepository; + private final OrderItemRepository orderItemRepository; + private final ShoppingCartRepository shoppingCartRepository; + private final AuthenticationService authenticationService; + private final OrderMapper orderMapper; + private final OrderItemMapper orderItemMapper; + private final UserRepository userRepository; + + @Override + public OrderResponseDto save(OrderRequestDto requestDto) { + Order order = new Order(); + order.setShippingAddress(requestDto.getShippingAddress()); + order.setOrderDate(LocalDateTime.now()); + ShoppingCart shoppingCart = shoppingCartRepository + .findByUserId(authenticationService.getUserId()) + .orElseThrow(() -> new EntityNotFoundException("Can't find shopping cart to place " + + "an order by user with id: " + authenticationService.getUserId())); + Set cartItems = shoppingCart.getCartItems(); + Set orderItems = new HashSet<>(); + BigDecimal total = BigDecimal.valueOf(0); + for (CartItem item : cartItems) { + OrderItem orderItem = new OrderItem(); + orderItem.setId(item.getId()); + orderItem.setOrder(order); + orderItem.setBook(item.getBook()); + orderItem.setPrice(item.getBook().getPrice()); + orderItem.setQuantity(item.getQuantity()); + orderItems.add(orderItem); + total = total.add(item.getBook().getPrice()); + } + order.setUser(userRepository.findById(authenticationService.getUserId()) + .orElseThrow(() -> new EntityNotFoundException("Can't find user with id: " + + authenticationService.getUserId()))); + order.setOrderItems(orderItems); + order.setTotal(total); + order.setStatus(Order.Status.NEW); + orderRepository.save(order); + return orderMapper.toDto(order); + } + + @Override + public List findAll(Pageable pageable) { + return orderRepository.findAll(pageable).stream() + .map(orderMapper::toDto) + .toList(); + } + + @Override + public OrderResponseDto updateOrderStatus(Long id, OrderUpdateRequestDto requestDto) { + Order order = orderRepository.findById(id) + .orElseThrow(() -> new EntityNotFoundException("Can't find order with id: " + id)); + order.setStatus(Order.Status.valueOf(requestDto.getStatus())); + return orderMapper.toDto(order); + } + + @Override + public List findAllOrderItems(Long orderId, Pageable pageable) { + Order order = orderRepository.findById(orderId) + .orElseThrow(() -> new EntityNotFoundException("Can't find order with id: " + + orderId)); + Set orderItems = order.getOrderItems(); + return orderItems.stream() + .map(orderItemMapper::toDto) + .toList(); + } + + @Override + public OrderItemDto findOrderItemById(Long orderId, Long itemId) { + OrderItem orderItem = orderItemRepository.findByOrderAndItemIds(orderId, itemId) + .orElseThrow(() -> new EntityNotFoundException(("Can't find order item with id %s " + + "for order with id %s").formatted(itemId, orderId)) + ); + return orderItemMapper.toDto(orderItem); + } +} diff --git a/src/main/resources/db/changelog/changes/12-create-statuses-table.yaml b/src/main/resources/db/changelog/changes/12-create-statuses-table.yaml new file mode 100644 index 0000000..6c8bf39 --- /dev/null +++ b/src/main/resources/db/changelog/changes/12-create-statuses-table.yaml @@ -0,0 +1,21 @@ +databaseChangeLog: + - changeSet: + id: create-statuses-table + author: tania + changes: + - createTable: + tableName: statuses + columns: + - column: + name: id + type: bigint + autoIncrement: true + constraints: + primaryKey: true + nullable: false + - column: + name: name + type: varchar(255) + constraints: + nullable: false + unique: true diff --git a/src/main/resources/db/changelog/changes/13-fill-statuses-table.yaml b/src/main/resources/db/changelog/changes/13-fill-statuses-table.yaml new file mode 100644 index 0000000..9ca9260 --- /dev/null +++ b/src/main/resources/db/changelog/changes/13-fill-statuses-table.yaml @@ -0,0 +1,25 @@ +databaseChangeLog: + - changeSet: + id: fill-statuses-table + author: tania + changes: + - insert: + tableName: statuses + columns: + - column: {name: name, value: "NEW"} + - insert: + tableName: statuses + columns: + - column: {name: name, value: "PROCESSING"} + - insert: + tableName: statuses + columns: + - column: {name: name, value: "SHIPPED"} + - insert: + tableName: statuses + columns: + - column: { name: name, value: "COMPLETED" } + - insert: + tableName: statuses + columns: + - column: { name: name, value: "CANCELLED" } diff --git a/src/main/resources/db/changelog/changes/14-create-orders-table.yaml b/src/main/resources/db/changelog/changes/14-create-orders-table.yaml new file mode 100644 index 0000000..5c54973 --- /dev/null +++ b/src/main/resources/db/changelog/changes/14-create-orders-table.yaml @@ -0,0 +1,49 @@ +databaseChangeLog: + - changeSet: + id: create-orders-table + author: tania + changes: + - createTable: + tableName: orders + columns: + - column: + name: id + type: bigint + autoIncrement: true + constraints: + primaryKey: true + nullable: false + - column: + name: user_id + type: bigint + constraints: + nullable: false + referencedTableName: users + referencedColumnNames: id + foreignKeyName: fk_orders_user_id + - column: + name: status + type: varchar(255) + constraints: + nullable: false + - column: + name: total + type: decimal(38,2) + constraints: + nullable: false + - column: + name: order_date + type: datetime + constraints: + nullable: false + - column: + name: shipping_address + type: varchar(255) + constraints: + nullable: false + - column: + name: is_deleted + type: boolean + defaultValueBoolean: false + constraints: + nullable: false diff --git a/src/main/resources/db/changelog/changes/15-create-order_items-table.yaml b/src/main/resources/db/changelog/changes/15-create-order_items-table.yaml new file mode 100644 index 0000000..40e7e4e --- /dev/null +++ b/src/main/resources/db/changelog/changes/15-create-order_items-table.yaml @@ -0,0 +1,47 @@ +databaseChangeLog: + - changeSet: + id: create-order_items-table + author: tania + changes: + - createTable: + tableName: order_items + columns: + - column: + name: id + type: bigint + autoIncrement: true + constraints: + primaryKey: true + nullable: false + - column: + name: order_id + type: bigint + constraints: + nullable: false + referencedTableName: orders + referencedColumnNames: id + foreignKeyName: fk_order_items_order_id + - column: + name: book_id + type: bigint + constraints: + nullable: false + referencedTableName: books + referencedColumnNames: id + foreignKeyName: fk_order_items_book_id + - column: + name: quantity + type: int + constraints: + nullable: false + - column: + name: price + type: decimal(10,2) + constraints: + nullable: false + - column: + name: is_deleted + type: boolean + defaultValueBoolean: false + constraints: + nullable: false diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 5a74dc5..0ed058a 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -20,4 +20,12 @@ databaseChangeLog: - include: file: db/changelog/changes/10-create-shopping_carts-table.yaml - include: - file: db/changelog/changes/11-create-cart_items-table.yaml \ No newline at end of file + file: db/changelog/changes/11-create-cart_items-table.yaml + - include: + file: db/changelog/changes/12-create-statuses-table.yaml + - include: + file: db/changelog/changes/13-fill-statuses-table.yaml + - include: + file: db/changelog/changes/14-create-orders-table.yaml + - include: + file: db/changelog/changes/15-create-order_items-table.yaml From b71edf081dce38a1eb99e0dce9c981677d57aa9a Mon Sep 17 00:00:00 2001 From: Tetiana Date: Thu, 12 Oct 2023 17:35:39 +0300 Subject: [PATCH 2/2] handled lazy initialization problem --- .../java/com/vozniuk/bookstore/model/Order.java | 3 +++ .../repository/OrderItemRepository.java | 8 ++++++++ .../bookstore/repository/OrderRepository.java | 16 ++++++++++++++++ .../bookstore/service/impl/OrderServiceImpl.java | 1 - 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/vozniuk/bookstore/model/Order.java b/src/main/java/com/vozniuk/bookstore/model/Order.java index 2e4d7ce..8920bf2 100644 --- a/src/main/java/com/vozniuk/bookstore/model/Order.java +++ b/src/main/java/com/vozniuk/bookstore/model/Order.java @@ -18,6 +18,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; +import org.hibernate.annotations.Cascade; +import org.hibernate.annotations.CascadeType; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; @@ -47,6 +49,7 @@ public class Order { @OneToMany(mappedBy = "order") @ToString.Exclude @EqualsAndHashCode.Exclude + @Cascade(CascadeType.PERSIST) private Set orderItems = new HashSet<>(); public enum Status { diff --git a/src/main/java/com/vozniuk/bookstore/repository/OrderItemRepository.java b/src/main/java/com/vozniuk/bookstore/repository/OrderItemRepository.java index fb6352d..7e5138e 100644 --- a/src/main/java/com/vozniuk/bookstore/repository/OrderItemRepository.java +++ b/src/main/java/com/vozniuk/bookstore/repository/OrderItemRepository.java @@ -2,11 +2,19 @@ import com.vozniuk.bookstore.model.OrderItem; import java.util.Optional; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; public interface OrderItemRepository extends JpaRepository { + @Override + @Query("SELECT oi FROM OrderItem oi " + + "LEFT JOIN FETCH oi.order o " + + "LEFT JOIN FETCH oi.book ") + Page findAll(Pageable pageable); + @Query("FROM OrderItem oi " + "LEFT JOIN FETCH oi.order o " + "WHERE oi.id = :itemId AND o.id = :orderId") diff --git a/src/main/java/com/vozniuk/bookstore/repository/OrderRepository.java b/src/main/java/com/vozniuk/bookstore/repository/OrderRepository.java index 2fe00ee..03ef861 100644 --- a/src/main/java/com/vozniuk/bookstore/repository/OrderRepository.java +++ b/src/main/java/com/vozniuk/bookstore/repository/OrderRepository.java @@ -1,7 +1,23 @@ package com.vozniuk.bookstore.repository; import com.vozniuk.bookstore.model.Order; +import java.util.Optional; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; public interface OrderRepository extends JpaRepository { + @Override + @Query("SELECT o FROM Order o LEFT JOIN FETCH o.orderItems oi " + + " LEFT JOIN FETCH oi.book ") + Page findAll(Pageable pageable); + + @Override + @Query("SELECT o FROM Order o " + + "LEFT JOIN FETCH o.orderItems oi " + + "LEFT JOIN FETCH oi.book " + + "WHERE o.id = :orderId") + Optional findById(@Param("orderId")Long orderId); } diff --git a/src/main/java/com/vozniuk/bookstore/service/impl/OrderServiceImpl.java b/src/main/java/com/vozniuk/bookstore/service/impl/OrderServiceImpl.java index ed17b11..0c35755 100644 --- a/src/main/java/com/vozniuk/bookstore/service/impl/OrderServiceImpl.java +++ b/src/main/java/com/vozniuk/bookstore/service/impl/OrderServiceImpl.java @@ -51,7 +51,6 @@ public OrderResponseDto save(OrderRequestDto requestDto) { BigDecimal total = BigDecimal.valueOf(0); for (CartItem item : cartItems) { OrderItem orderItem = new OrderItem(); - orderItem.setId(item.getId()); orderItem.setOrder(order); orderItem.setBook(item.getBook()); orderItem.setPrice(item.getBook().getPrice());