Skip to content

Commit

Permalink
Merge pull request #11 from fedorovychh/development-order
Browse files Browse the repository at this point in the history
[Book_Store] order functionality
  • Loading branch information
fedorovychh authored Jan 4, 2024
2 parents f54fd36 + 6e773da commit f4ef4d9
Show file tree
Hide file tree
Showing 18 changed files with 547 additions and 0 deletions.
79 changes: 79 additions & 0 deletions src/main/java/com/app/bookstore/controller/OrderController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.app.bookstore.controller;

import com.app.bookstore.dto.order.OrderRequestDto;
import com.app.bookstore.dto.order.OrderResponseDto;
import com.app.bookstore.dto.order.UpdateOrderRequestDto;
import com.app.bookstore.dto.order.item.OrderItemResponseDto;
import com.app.bookstore.model.User;
import com.app.bookstore.service.order.OrderService;
import com.app.bookstore.service.order.item.OrderItemService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
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;

@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/orders")
@Tag(name = "Order management", description = "Endpoints for managing orders")
public class OrderController {
private final OrderService orderService;
private final OrderItemService orderItemService;

@PreAuthorize("hasRole('ROLE_USER')")
@PostMapping
@Operation(summary = "Place order", description = "Place order")
public OrderResponseDto placeOrder(
Authentication authentication,
@RequestBody OrderRequestDto requestDto
) {
User user = (User) authentication.getPrincipal();
return orderService.placeOrder(user.getId(), requestDto);
}

@PreAuthorize("hasRole('ROLE_USER')")
@GetMapping
@Operation(summary = "Get all orders", description = "Return all orders")
public List<OrderResponseDto> getAll(Authentication authentication) {
User user = (User) authentication.getPrincipal();
return orderService.getAll(user.getId());
}

@PreAuthorize("hasRole('ROLE_ADMIN')")
@PatchMapping("/{id}")
@Operation(summary = "Change order status", description = "Change order status")
public OrderResponseDto updateStatus(
@PathVariable Long id,
@RequestBody UpdateOrderRequestDto requestDto) {
return orderService.updateStatus(id, requestDto);
}

@PreAuthorize("hasRole('ROLE_USER')")
@GetMapping("/{id}/items")
@Operation(
summary = "Get all items by order id",
description = "Retrieve all OrderItems for a specific order"
)
public List<OrderItemResponseDto> getAllById(@PathVariable Long id) {
return orderItemService.getAllById(id);
}

@PreAuthorize("hasRole('ROLE_USER')")
@GetMapping("/{id}/items/{itemId}")
@Operation(
summary = "Get item from order by id",
description = "Retrieve specific OrderItem from a specific order"
)
public OrderItemResponseDto getItemById(@PathVariable Long id, @PathVariable Long itemId) {
return orderItemService.getItemById(id, itemId);
}
}
10 changes: 10 additions & 0 deletions src/main/java/com/app/bookstore/dto/order/OrderRequestDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.app.bookstore.dto.order;

import lombok.Data;
import org.hibernate.validator.constraints.Length;

@Data
public class OrderRequestDto {
@Length(min = 4, max = 60, message = "can't be less than 4 and more than 60 letters")
private String shippingAddress;
}
17 changes: 17 additions & 0 deletions src/main/java/com/app/bookstore/dto/order/OrderResponseDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.app.bookstore.dto.order;

import com.app.bookstore.dto.order.item.OrderItemResponseDto;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import lombok.Data;

@Data
public class OrderResponseDto {
private Long id;
private Long userId;
private List<OrderItemResponseDto> orderItems;
private LocalDateTime orderDate;
private BigDecimal total;
private String status;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.app.bookstore.dto.order;

import com.app.bookstore.model.Order;
import jakarta.validation.constraints.NotNull;
import lombok.Data;

@Data
public class UpdateOrderRequestDto {
@NotNull
private Order.Status status;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.app.bookstore.dto.order.item;

import lombok.Data;

@Data
public class OrderItemResponseDto {
private Long id;
private Long bookId;
private int quantity;
}
13 changes: 13 additions & 0 deletions src/main/java/com/app/bookstore/mapper/OrderItemMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.app.bookstore.mapper;

import com.app.bookstore.config.MapperConfig;
import com.app.bookstore.dto.order.item.OrderItemResponseDto;
import com.app.bookstore.model.OrderItem;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

@Mapper(config = MapperConfig.class)
public interface OrderItemMapper {
@Mapping(target = "bookId", source = "book.id")
OrderItemResponseDto toDto(OrderItem orderItem);
}
16 changes: 16 additions & 0 deletions src/main/java/com/app/bookstore/mapper/OrderMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.app.bookstore.mapper;

import com.app.bookstore.config.MapperConfig;
import com.app.bookstore.dto.order.OrderRequestDto;
import com.app.bookstore.dto.order.OrderResponseDto;
import com.app.bookstore.model.Order;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

@Mapper(config = MapperConfig.class, uses = OrderItemMapper.class)
public interface OrderMapper {
@Mapping(target = "userId", source = "user.id")
OrderResponseDto toDto(Order order);

Order toOrder(OrderRequestDto requestDto);
}
58 changes: 58 additions & 0 deletions src/main/java/com/app/bookstore/model/Order.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.app.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.OneToMany;
import jakarta.persistence.Table;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Set;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import org.hibernate.type.SqlTypes;

@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
@ToString.Exclude
@EqualsAndHashCode.Exclude
@JoinColumn(name = "user_id", nullable = false)
private User user;
@JdbcTypeCode(SqlTypes.VARCHAR)
@Column(nullable = false)
private Status status;
@Column(nullable = false)
private BigDecimal total;
@CreationTimestamp
@Column(nullable = false)
private LocalDateTime orderDate;
@Column(nullable = false)
private String shippingAddress;
@OneToMany(mappedBy = "order")
@ToString.Exclude
@EqualsAndHashCode.Exclude
private Set<OrderItem> orderItems;
@Column(nullable = false)
private boolean isDeleted = false;

public enum Status {
PROCESSING, COMPLETED
}
}
43 changes: 43 additions & 0 deletions src/main/java/com/app/bookstore/model/OrderItem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.app.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.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
@ToString.Exclude
@EqualsAndHashCode.Exclude
@JoinColumn(name = "order_id", nullable = false)
private Order order;
@ManyToOne
@ToString.Exclude
@EqualsAndHashCode.Exclude
@JoinColumn(name = "book_id", nullable = false)
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,13 @@
package com.app.bookstore.repository.order;

import com.app.bookstore.model.Order;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
@Query("SELECT o FROM Order o JOIN FETCH o.orderItems is WHERE o.user.id = :id")
List<Order> findAllById(Long id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.app.bookstore.repository.order.item;

import com.app.bookstore.model.OrderItem;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

@Repository
public interface OrderItemRepository extends JpaRepository<OrderItem, Long> {
@Query("SELECT oi FROM OrderItem oi "
+ "JOIN FETCH oi.order "
+ "JOIN FETCH oi.book "
+ "WHERE oi.order.id = :id")
List<OrderItem> findAllById(Long id);

@Query("SELECT oi FROM OrderItem oi "
+ "JOIN FETCH oi.order "
+ "JOIN FETCH oi.book "
+ "WHERE oi.id = :itemId AND oi.order.id = :id")
Optional<OrderItem> findById(Long id, Long itemId);
}
14 changes: 14 additions & 0 deletions src/main/java/com/app/bookstore/service/order/OrderService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.app.bookstore.service.order;

import com.app.bookstore.dto.order.OrderRequestDto;
import com.app.bookstore.dto.order.OrderResponseDto;
import com.app.bookstore.dto.order.UpdateOrderRequestDto;
import java.util.List;

public interface OrderService {
OrderResponseDto placeOrder(Long id, OrderRequestDto requestDto);

List<OrderResponseDto> getAll(Long id);

OrderResponseDto updateStatus(Long id, UpdateOrderRequestDto requestDto);
}
Loading

0 comments on commit f4ef4d9

Please sign in to comment.