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 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 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> listMine() { List orders = orderRepository.findByUserIdOrderByCreatedAtDesc(AuthContext.get().getId()); List result = new ArrayList<>(); for (Order order : orders) { result.add(new OrderDetail(order, orderItemRepository.findByOrderId(order.getId()))); } return ApiResponse.ok(result); } @GetMapping("/{id}") public ApiResponse 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 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 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> listAll() { List orders = orderRepository.findAll(); List 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 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 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 items; public OrderDetail(Order order, List items) { this.order = order; this.items = items; } } }