Skip to content

Commit

Permalink
Merge pull request #9 from BlueVioletTeti/dev-order-model
Browse files Browse the repository at this point in the history
added order functionality
  • Loading branch information
BlueVioletTeti authored Oct 13, 2023
2 parents b85d21d + b71edf0 commit b807ae6
Show file tree
Hide file tree
Showing 18 changed files with 572 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -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<OrderResponseDto> 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<OrderItemDto> 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);
}
}
10 changes: 10 additions & 0 deletions src/main/java/com/vozniuk/bookstore/dto/order/OrderItemDto.java
Original file line number Diff line number Diff line change
@@ -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;
}
11 changes: 11 additions & 0 deletions src/main/java/com/vozniuk/bookstore/dto/order/OrderRequestDto.java
Original file line number Diff line number Diff line change
@@ -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;

}
Original file line number Diff line number Diff line change
@@ -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<OrderItemDto> orderItems;
private LocalDateTime orderDate;
private BigInteger total;
private String status;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.vozniuk.bookstore.dto.order;

import lombok.Data;

@Data
public class OrderUpdateRequestDto {
private String status;
}
16 changes: 16 additions & 0 deletions src/main/java/com/vozniuk/bookstore/mapper/OrderItemMapper.java
Original file line number Diff line number Diff line change
@@ -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);
}
16 changes: 16 additions & 0 deletions src/main/java/com/vozniuk/bookstore/mapper/OrderMapper.java
Original file line number Diff line number Diff line change
@@ -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);
}
62 changes: 62 additions & 0 deletions src/main/java/com/vozniuk/bookstore/model/Order.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
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.Cascade;
import org.hibernate.annotations.CascadeType;
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
@Cascade(CascadeType.PERSIST)
private Set<OrderItem> orderItems = new HashSet<>();

public enum Status {
NEW,
PROCESSING,
SHIPPED,
COMPLETED,
CANCELLED
}
}
44 changes: 44 additions & 0 deletions src/main/java/com/vozniuk/bookstore/model/OrderItem.java
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.vozniuk.bookstore.repository;

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<OrderItem, Long> {
@Override
@Query("SELECT oi FROM OrderItem oi "
+ "LEFT JOIN FETCH oi.order o "
+ "LEFT JOIN FETCH oi.book ")
Page<OrderItem> findAll(Pageable pageable);

@Query("FROM OrderItem oi "
+ "LEFT JOIN FETCH oi.order o "
+ "WHERE oi.id = :itemId AND o.id = :orderId")
Optional<OrderItem> findByOrderAndItemIds(@Param("orderId")Long orderId,
@Param("itemId") Long itemId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +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<Order, Long> {
@Override
@Query("SELECT o FROM Order o LEFT JOIN FETCH o.orderItems oi "
+ " LEFT JOIN FETCH oi.book ")
Page<Order> 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<Order> findById(@Param("orderId")Long orderId);
}
20 changes: 20 additions & 0 deletions src/main/java/com/vozniuk/bookstore/service/OrderService.java
Original file line number Diff line number Diff line change
@@ -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<OrderResponseDto> findAll(Pageable pageable);

OrderResponseDto updateOrderStatus(Long id, OrderUpdateRequestDto requestDto);

List<OrderItemDto> findAllOrderItems(Long orderId, Pageable pageable);

OrderItemDto findOrderItemById(Long orderId, Long itemId);
}
Loading

0 comments on commit b807ae6

Please sign in to comment.