187 lines
7.2 KiB
Java
187 lines
7.2 KiB
Java
package com.flower.order;
|
|
|
|
import com.flower.common.ApiException;
|
|
import com.flower.common.ApiResponse;
|
|
import com.flower.product.Product;
|
|
import com.flower.product.ProductRepository;
|
|
import com.flower.security.AdminOnly;
|
|
import com.flower.security.AuthContext;
|
|
import com.flower.user.Address;
|
|
import com.flower.user.AddressRepository;
|
|
import lombok.Data;
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
import javax.validation.Valid;
|
|
import javax.validation.constraints.NotEmpty;
|
|
import java.math.BigDecimal;
|
|
import java.time.LocalDateTime;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.UUID;
|
|
|
|
@RestController
|
|
@RequestMapping("/api/orders")
|
|
public class OrderController {
|
|
private final OrderRepository orderRepository;
|
|
private final OrderItemRepository orderItemRepository;
|
|
private final ProductRepository productRepository;
|
|
private final AddressRepository addressRepository;
|
|
|
|
public OrderController(OrderRepository orderRepository,
|
|
OrderItemRepository orderItemRepository,
|
|
ProductRepository productRepository,
|
|
AddressRepository addressRepository) {
|
|
this.orderRepository = orderRepository;
|
|
this.orderItemRepository = orderItemRepository;
|
|
this.productRepository = productRepository;
|
|
this.addressRepository = addressRepository;
|
|
}
|
|
|
|
@PostMapping
|
|
public ApiResponse<OrderDetail> create(@Valid @RequestBody CreateOrderRequest request) {
|
|
Address address = addressRepository.findById(request.getAddressId())
|
|
.orElseThrow(() -> new ApiException(404, "地址不存在"));
|
|
if (!address.getUserId().equals(AuthContext.get().getId())) {
|
|
throw new ApiException(403, "无权限");
|
|
}
|
|
List<OrderItem> items = new ArrayList<>();
|
|
BigDecimal total = BigDecimal.ZERO;
|
|
for (CreateOrderItem item : request.getItems()) {
|
|
Product product = productRepository.findById(item.getProductId())
|
|
.orElseThrow(() -> new ApiException(404, "商品不存在"));
|
|
if (!"ON".equals(product.getStatus())) {
|
|
throw new ApiException(400, "商品已下架");
|
|
}
|
|
if (product.getStock() < item.getQuantity()) {
|
|
throw new ApiException(400, "库存不足");
|
|
}
|
|
product.setStock(product.getStock() - item.getQuantity());
|
|
productRepository.save(product);
|
|
OrderItem orderItem = new OrderItem();
|
|
orderItem.setProductId(product.getId());
|
|
orderItem.setProductName(product.getName());
|
|
orderItem.setProductPrice(product.getPrice());
|
|
orderItem.setQuantity(item.getQuantity());
|
|
orderItem.setProductCover(product.getCoverUrl());
|
|
items.add(orderItem);
|
|
total = total.add(product.getPrice().multiply(new BigDecimal(item.getQuantity())));
|
|
}
|
|
Order order = new Order();
|
|
order.setOrderNo("NO" + UUID.randomUUID().toString().replace("-", "").substring(0, 12));
|
|
order.setUserId(AuthContext.get().getId());
|
|
order.setStatus("CREATED");
|
|
order.setTotalAmount(total);
|
|
order.setReceiverName(address.getRecipientName());
|
|
order.setReceiverPhone(address.getPhone());
|
|
order.setReceiverAddress(String.join(" ", safe(address.getProvince()),
|
|
safe(address.getCity()), safe(address.getDistrict()), safe(address.getDetail())));
|
|
orderRepository.save(order);
|
|
for (OrderItem item : items) {
|
|
item.setOrderId(order.getId());
|
|
orderItemRepository.save(item);
|
|
}
|
|
return ApiResponse.ok(new OrderDetail(order, items));
|
|
}
|
|
|
|
@GetMapping
|
|
public ApiResponse<List<OrderDetail>> listMine() {
|
|
List<Order> orders = orderRepository.findByUserIdOrderByCreatedAtDesc(AuthContext.get().getId());
|
|
List<OrderDetail> result = new ArrayList<>();
|
|
for (Order order : orders) {
|
|
result.add(new OrderDetail(order, orderItemRepository.findByOrderId(order.getId())));
|
|
}
|
|
return ApiResponse.ok(result);
|
|
}
|
|
|
|
@GetMapping("/{id}")
|
|
public ApiResponse<OrderDetail> detail(@PathVariable Long id) {
|
|
Order order = orderRepository.findById(id).orElseThrow(() -> new ApiException(404, "订单不存在"));
|
|
if (!order.getUserId().equals(AuthContext.get().getId())) {
|
|
throw new ApiException(403, "无权限");
|
|
}
|
|
return ApiResponse.ok(new OrderDetail(order, orderItemRepository.findByOrderId(id)));
|
|
}
|
|
|
|
@PutMapping("/{id}/cancel")
|
|
public ApiResponse<Order> cancel(@PathVariable Long id) {
|
|
Order order = orderRepository.findById(id).orElseThrow(() -> new ApiException(404, "订单不存在"));
|
|
if (!order.getUserId().equals(AuthContext.get().getId())) {
|
|
throw new ApiException(403, "无权限");
|
|
}
|
|
if (!"CREATED".equals(order.getStatus())) {
|
|
throw new ApiException(400, "订单无法取消");
|
|
}
|
|
order.setStatus("CANCELED");
|
|
orderRepository.save(order);
|
|
return ApiResponse.ok(order);
|
|
}
|
|
|
|
@PostMapping("/{id}/pay")
|
|
public ApiResponse<Order> pay(@PathVariable Long id) {
|
|
Order order = orderRepository.findById(id).orElseThrow(() -> new ApiException(404, "订单不存在"));
|
|
if (!order.getUserId().equals(AuthContext.get().getId())) {
|
|
throw new ApiException(403, "无权限");
|
|
}
|
|
if (!"CREATED".equals(order.getStatus())) {
|
|
throw new ApiException(400, "订单无法支付");
|
|
}
|
|
order.setStatus("PAID");
|
|
order.setPayAt(LocalDateTime.now());
|
|
orderRepository.save(order);
|
|
return ApiResponse.ok(order);
|
|
}
|
|
|
|
@AdminOnly
|
|
@GetMapping("/admin/all")
|
|
public ApiResponse<List<OrderDetail>> listAll() {
|
|
List<Order> orders = orderRepository.findAll();
|
|
List<OrderDetail> result = new ArrayList<>();
|
|
for (Order order : orders) {
|
|
result.add(new OrderDetail(order, orderItemRepository.findByOrderId(order.getId())));
|
|
}
|
|
return ApiResponse.ok(result);
|
|
}
|
|
|
|
@AdminOnly
|
|
@PutMapping("/admin/{id}/status")
|
|
public ApiResponse<Order> updateStatus(@PathVariable Long id, @RequestBody UpdateStatusRequest request) {
|
|
Order order = orderRepository.findById(id).orElseThrow(() -> new ApiException(404, "订单不存在"));
|
|
order.setStatus(request.getStatus());
|
|
orderRepository.save(order);
|
|
return ApiResponse.ok(order);
|
|
}
|
|
|
|
private String safe(String value) {
|
|
return value == null ? "" : value;
|
|
}
|
|
|
|
@Data
|
|
public static class CreateOrderRequest {
|
|
private Long addressId;
|
|
@NotEmpty
|
|
private List<CreateOrderItem> items;
|
|
}
|
|
|
|
@Data
|
|
public static class CreateOrderItem {
|
|
private Long productId;
|
|
private Integer quantity;
|
|
}
|
|
|
|
@Data
|
|
public static class UpdateStatusRequest {
|
|
private String status;
|
|
}
|
|
|
|
@Data
|
|
public static class OrderDetail {
|
|
private Order order;
|
|
private List<OrderItem> items;
|
|
|
|
public OrderDetail(Order order, List<OrderItem> items) {
|
|
this.order = order;
|
|
this.items = items;
|
|
}
|
|
}
|
|
}
|