This commit is contained in:
王子琦
2026-01-13 13:55:40 +08:00
parent 6affd0c77e
commit f58e05d962
72 changed files with 3251 additions and 0 deletions

View File

@@ -0,0 +1,186 @@
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;
}
}
}