Skip to content
87 changes: 87 additions & 0 deletions src/main/java/com/springm/store/controller/OrderController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.springm.store.controller;

import com.springm.store.dto.order.AddShippingAddressDto;
import com.springm.store.dto.order.OrderResponseDto;
import com.springm.store.dto.order.UpdateOrderStatusDto;
import com.springm.store.dto.order.item.OrderItemDto;
import com.springm.store.service.OrderService;
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.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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")
@RestController
@RequiredArgsConstructor
@RequestMapping("/orders")
public class OrderController {
private final OrderService orderService;

@PostMapping
@PreAuthorize("hasAnyRole('USER', 'ADMIN')")
@Operation(summary = "Place an order", description = "Place an order")
public ResponseEntity<OrderResponseDto> placeOrder(
@RequestBody AddShippingAddressDto shippingAddress
) {
return new ResponseEntity<OrderResponseDto>(
orderService.placeOrder(shippingAddress),
HttpStatus.CREATED
);
}

@GetMapping
@PreAuthorize("hasAnyRole('USER', 'ADMIN')")
@Operation(summary = "Receive orders history", description = "Receive orders history")
public ResponseEntity<List<OrderResponseDto>> getOrderHistory() {
return new ResponseEntity<List<OrderResponseDto>>(
orderService.receiveOrderHistory(),
HttpStatus.OK
);
}

@PatchMapping("/{id}")
@PreAuthorize("hasRole('ADMIN')")
@Operation(
summary = "Update order status",
description = "Updates order status with specified ID"
)
public ResponseEntity<OrderResponseDto> updateStatus(
@PathVariable Long id,
@RequestBody UpdateOrderStatusDto orderStatusDto
) {
return new ResponseEntity<OrderResponseDto>(
orderService.updateOrderStatus(id, orderStatusDto),
HttpStatus.NO_CONTENT
);
}

@GetMapping("/{orderId}/items")
@PreAuthorize("hasAnyRole('USER', 'ADMIN')")
public ResponseEntity<List<OrderItemDto>> getOrderItems(@PathVariable Long orderId) {
return new ResponseEntity<List<OrderItemDto>>(
orderService.getItemsByOrderId(orderId),
HttpStatus.OK
);
}

@GetMapping("/{orderId}/items/{id}")
@PreAuthorize("hasAnyRole('USER', 'ADMIN')")
public ResponseEntity<OrderItemDto> getOrderItem(@PathVariable Long orderId,
@PathVariable Long id) {
return new ResponseEntity<OrderItemDto>(
orderService.getItemByOrderIdAndItemId(orderId, id),
HttpStatus.OK
);
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.springm.store.dto.cart.item;

import java.math.BigDecimal;
import lombok.Getter;
import lombok.Setter;

Expand All @@ -10,4 +11,5 @@ public class CartItemDto {
private Long bookId;
private String bookTitle;
private int quantity;
private BigDecimal price;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.springm.store.dto.order;

import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class AddShippingAddressDto {
@NotBlank
private String shippingAddress;
}
20 changes: 20 additions & 0 deletions src/main/java/com/springm/store/dto/order/OrderResponseDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.springm.store.dto.order;

import com.springm.store.dto.order.item.OrderItemDto;
import com.springm.store.model.Order;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class OrderResponseDto {
private Long id;
private Long userId;
private LocalDateTime orderDate;
private BigDecimal total;
private Order.Status orderStatus;
private List<OrderItemDto> orderItems;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.springm.store.dto.order;

import com.springm.store.model.Order;
import com.springm.store.validation.order.Status;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class UpdateOrderStatusDto {
@Status(enumClass = Order.Status.class)
private Order.Status status;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add validation

}
15 changes: 15 additions & 0 deletions src/main/java/com/springm/store/dto/order/item/OrderItemDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.springm.store.dto.order.item;

import java.math.BigDecimal;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class OrderItemDto {
private Long id;
private Long bookId;
private String bookTitle;
private int quantity;
private BigDecimal price;
}
24 changes: 24 additions & 0 deletions src/main/java/com/springm/store/mapper/OrderItemMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.springm.store.mapper;

import com.springm.store.config.MapperConfig;
import com.springm.store.dto.cart.item.CartItemDto;
import com.springm.store.dto.order.item.OrderItemDto;
import com.springm.store.model.OrderItem;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

@Mapper(config = MapperConfig.class)
public interface OrderItemMapper {

@Mapping(target = "id", ignore = true)
OrderItemDto toDtoFromCart(CartItemDto cartItemDto);

@Mapping(source = "bookId", target = "book.id")
@Mapping(source = "bookTitle", target = "book.title")
OrderItem toModel(OrderItemDto orderItemDto);

@Mapping(source = "book.id", target = "bookId")
@Mapping(source = "book.title", target = "bookTitle")
OrderItemDto toDto(OrderItem orderItem);

}
17 changes: 17 additions & 0 deletions src/main/java/com/springm/store/mapper/OrderMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.springm.store.mapper;

import com.springm.store.config.MapperConfig;
import com.springm.store.dto.order.OrderResponseDto;
import com.springm.store.model.Order;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

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

}
3 changes: 3 additions & 0 deletions src/main/java/com/springm/store/model/CartItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.math.BigDecimal;
import lombok.Getter;
import lombok.Setter;

Expand All @@ -32,4 +33,6 @@ public class CartItem {
@Column(nullable = false)
private int quantity;

@Column(nullable = false)
private BigDecimal price;
}
66 changes: 66 additions & 0 deletions src/main/java/com/springm/store/model/Order.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.springm.store.model;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
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.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.SQLRestriction;

@Entity
@Table(name = "orders")
@SQLDelete(sql = "UPDATE orders SET is_deleted = true WHERE id=?")
@SQLRestriction("is_deleted = false")
@Getter
@Setter
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user;

@Column(nullable = false)
@Enumerated(EnumType.STRING)
private Status status;

@Column(nullable = false)
private BigDecimal total;

@Column(nullable = false)
private LocalDateTime orderDate;

@Column(nullable = false)
private String shippingAddress;

@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
@ToString.Exclude
@EqualsAndHashCode.Exclude
private Set<OrderItem> orderItems = new HashSet<>();

public enum Status {
ORDER_PLACED,
PENDING,
DELIVERED,
COMPLETED
}
}
38 changes: 38 additions & 0 deletions src/main/java/com/springm/store/model/OrderItem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.springm.store.model;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
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.Getter;
import lombok.Setter;

@Entity
@Table(name = "order_items")
@Getter
@Setter
public class OrderItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(optional = false, fetch = FetchType.LAZY)
@JoinColumn(name = "order_id", nullable = false)
private Order order;

@ManyToOne(optional = false, fetch = FetchType.LAZY)
@JoinColumn(name = "book_id", nullable = false)
private Book book;

@Column(nullable = false)
private int quantity;

@Column(nullable = false)
private BigDecimal price;
}
4 changes: 4 additions & 0 deletions src/main/java/com/springm/store/model/ShoppingCart.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,8 @@ public class ShoppingCart {

@Column(nullable = false)
private boolean isDeleted = false;

public void clear() {
cartItems.clear();
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.springm.store.repository.cart;

import com.springm.store.model.ShoppingCart;
import com.springm.store.model.User;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ShoppingCartRepository extends JpaRepository<ShoppingCart, Long> {
Optional<ShoppingCart> findByUserId(Long userId);

Optional<ShoppingCart> findByUser(User user);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.springm.store.repository.order;

import com.springm.store.model.Order;
import com.springm.store.model.User;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;

public interface OrderRepository extends JpaRepository<Order, Long> {
List<Order> findByUser(User user);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.springm.store.repository.order.item;

import com.springm.store.model.OrderItem;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;

public interface OrderItemRepository extends JpaRepository<OrderItem, Long> {
List<OrderItem> findByOrderId(Long orderId);

Optional<OrderItem> findByOrderIdAndId(Long orderId, Long id);

}
19 changes: 19 additions & 0 deletions src/main/java/com/springm/store/service/OrderService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.springm.store.service;

import com.springm.store.dto.order.AddShippingAddressDto;
import com.springm.store.dto.order.OrderResponseDto;
import com.springm.store.dto.order.UpdateOrderStatusDto;
import com.springm.store.dto.order.item.OrderItemDto;
import java.util.List;

public interface OrderService {
OrderResponseDto placeOrder(AddShippingAddressDto shippingAddressDto);

List<OrderResponseDto> receiveOrderHistory();

OrderResponseDto updateOrderStatus(Long orderId, UpdateOrderStatusDto orderStatus);

List<OrderItemDto> getItemsByOrderId(Long orderId);

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