Initial commit
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
package com.maternalmall;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class MaternalMallApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(MaternalMallApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.maternalmall.common;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ApiResponse<T> {
|
||||
private int code;
|
||||
private String message;
|
||||
private T data;
|
||||
|
||||
public static <T> ApiResponse<T> ok(T data) {
|
||||
return new ApiResponse<>(0, "ok", data);
|
||||
}
|
||||
|
||||
public static ApiResponse<Void> ok() {
|
||||
return new ApiResponse<>(0, "ok", null);
|
||||
}
|
||||
|
||||
public static ApiResponse<Void> fail(String message) {
|
||||
return new ApiResponse<>(-1, message, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.maternalmall.common;
|
||||
|
||||
public class BizException extends RuntimeException {
|
||||
public BizException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.maternalmall.common;
|
||||
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
@ExceptionHandler(BizException.class)
|
||||
public ApiResponse<Void> handleBiz(BizException ex) {
|
||||
return ApiResponse.fail(ex.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public ApiResponse<Void> handleValid(MethodArgumentNotValidException ex) {
|
||||
String msg = ex.getBindingResult().getFieldErrors().stream().findFirst()
|
||||
.map(e -> e.getField() + ":" + e.getDefaultMessage()).orElse("参数错误");
|
||||
return ApiResponse.fail(msg);
|
||||
}
|
||||
|
||||
@ExceptionHandler(ConstraintViolationException.class)
|
||||
public ApiResponse<Void> handleConstraint(ConstraintViolationException ex) {
|
||||
return ApiResponse.fail(ex.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public ApiResponse<Void> handleUnknown(Exception ex) {
|
||||
return ApiResponse.fail(ex.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.maternalmall.config;
|
||||
|
||||
import com.maternalmall.domain.User;
|
||||
|
||||
public class AuthContext {
|
||||
public static final String CURRENT_USER = "CURRENT_USER";
|
||||
|
||||
public static User getUser(jakarta.servlet.http.HttpServletRequest request) {
|
||||
return (User) request.getAttribute(CURRENT_USER);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.maternalmall.config;
|
||||
|
||||
import com.maternalmall.domain.User;
|
||||
import com.maternalmall.repository.UserRepository;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@Component
|
||||
public class AuthInterceptor implements HandlerInterceptor {
|
||||
private final UserRepository userRepository;
|
||||
|
||||
@Value("${app.token-header:X-Token}")
|
||||
private String tokenHeader;
|
||||
|
||||
private static final Set<String> PUBLIC_PREFIX = Set.of(
|
||||
"/api/auth/login",
|
||||
"/api/auth/register",
|
||||
"/api/public"
|
||||
);
|
||||
|
||||
public AuthInterceptor(UserRepository userRepository) {
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
// Let browser CORS preflight pass without auth token.
|
||||
if (HttpMethod.OPTIONS.matches(request.getMethod())) {
|
||||
response.setStatus(HttpServletResponse.SC_OK);
|
||||
return true;
|
||||
}
|
||||
|
||||
String uri = request.getRequestURI();
|
||||
if (uri.equals("/") || uri.startsWith("/error") || PUBLIC_PREFIX.stream().anyMatch(uri::startsWith)) {
|
||||
return true;
|
||||
}
|
||||
String token = request.getHeader(tokenHeader);
|
||||
if (token == null || token.isBlank()) {
|
||||
response.setStatus(401);
|
||||
response.getWriter().write("{\"code\":401,\"message\":\"请先登录\",\"data\":null}");
|
||||
return false;
|
||||
}
|
||||
User user = userRepository.findByToken(token).orElse(null);
|
||||
if (user == null || !Boolean.TRUE.equals(user.getEnabled())) {
|
||||
response.setStatus(401);
|
||||
response.getWriter().write("{\"code\":401,\"message\":\"登录状态无效\",\"data\":null}");
|
||||
return false;
|
||||
}
|
||||
request.setAttribute(AuthContext.CURRENT_USER, user);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.maternalmall.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class WebMvcConfig implements WebMvcConfigurer {
|
||||
private final AuthInterceptor authInterceptor;
|
||||
|
||||
public WebMvcConfig(AuthInterceptor authInterceptor) {
|
||||
this.authInterceptor = authInterceptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(authInterceptor).addPathPatterns("/**");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**").allowedOrigins("*").allowedMethods("*").allowedHeaders("*");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
package com.maternalmall.controller;
|
||||
|
||||
import com.maternalmall.common.ApiResponse;
|
||||
import com.maternalmall.config.AuthContext;
|
||||
import com.maternalmall.domain.*;
|
||||
import com.maternalmall.service.MallService;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/admin")
|
||||
public class AdminController {
|
||||
private final MallService mallService;
|
||||
|
||||
public AdminController(MallService mallService) {
|
||||
this.mallService = mallService;
|
||||
}
|
||||
|
||||
private void check(User user) {
|
||||
mallService.requireRole(user, UserRole.ADMIN);
|
||||
}
|
||||
|
||||
@GetMapping("/overview")
|
||||
public ApiResponse<Map<String, Object>> overview(HttpServletRequest request) {
|
||||
check(AuthContext.getUser(request));
|
||||
return ApiResponse.ok(mallService.adminOverview());
|
||||
}
|
||||
|
||||
@GetMapping("/orders")
|
||||
public ApiResponse<List<Orders>> orders(HttpServletRequest request) {
|
||||
check(AuthContext.getUser(request));
|
||||
return ApiResponse.ok(mallService.adminOrders());
|
||||
}
|
||||
|
||||
@PutMapping("/orders/{id}")
|
||||
public ApiResponse<Orders> updateOrder(HttpServletRequest request, @PathVariable Long id, @RequestBody Map<String, String> body) {
|
||||
check(AuthContext.getUser(request));
|
||||
return ApiResponse.ok(mallService.adminUpdateOrder(id, body.get("status"), body.getOrDefault("logisticsInfo", "")));
|
||||
}
|
||||
|
||||
@GetMapping("/orders/risk")
|
||||
public ApiResponse<List<Map<String, Object>>> riskOrders(HttpServletRequest request) {
|
||||
check(AuthContext.getUser(request));
|
||||
return ApiResponse.ok(mallService.adminRiskOrders());
|
||||
}
|
||||
|
||||
@PutMapping("/orders/{id}/refund-audit")
|
||||
public ApiResponse<Orders> auditRefund(HttpServletRequest request, @PathVariable Long id, @RequestBody Map<String, Object> body) {
|
||||
check(AuthContext.getUser(request));
|
||||
boolean approve = Boolean.parseBoolean(String.valueOf(body.getOrDefault("approve", false)));
|
||||
String remark = String.valueOf(body.getOrDefault("remark", ""));
|
||||
return ApiResponse.ok(mallService.adminAuditRefund(id, approve, remark));
|
||||
}
|
||||
|
||||
@PutMapping("/orders/{id}/ship-audit")
|
||||
public ApiResponse<Orders> auditShipment(HttpServletRequest request, @PathVariable Long id, @RequestBody Map<String, Object> body) {
|
||||
check(AuthContext.getUser(request));
|
||||
boolean approve = Boolean.parseBoolean(String.valueOf(body.getOrDefault("approve", true)));
|
||||
String remark = String.valueOf(body.getOrDefault("remark", ""));
|
||||
return ApiResponse.ok(mallService.adminAuditShipment(id, approve, remark));
|
||||
}
|
||||
|
||||
@GetMapping("/merchant-applications")
|
||||
public ApiResponse<List<Map<String, Object>>> merchantApplications(HttpServletRequest request) {
|
||||
check(AuthContext.getUser(request));
|
||||
return ApiResponse.ok(mallService.adminMerchantApplications());
|
||||
}
|
||||
|
||||
@PutMapping("/merchant-applications/{id}")
|
||||
public ApiResponse<MerchantApplication> auditMerchant(HttpServletRequest request, @PathVariable Long id, @RequestBody Map<String, String> body) {
|
||||
check(AuthContext.getUser(request));
|
||||
return ApiResponse.ok(mallService.adminAuditApplication(id, body.get("status"), body.getOrDefault("remark", "")));
|
||||
}
|
||||
|
||||
@GetMapping("/users")
|
||||
public ApiResponse<List<User>> users(HttpServletRequest request) {
|
||||
check(AuthContext.getUser(request));
|
||||
return ApiResponse.ok(mallService.adminUsers());
|
||||
}
|
||||
|
||||
@PostMapping("/users")
|
||||
public ApiResponse<User> saveUser(HttpServletRequest request, @RequestBody User user) {
|
||||
check(AuthContext.getUser(request));
|
||||
return ApiResponse.ok(mallService.adminSaveUser(user));
|
||||
}
|
||||
|
||||
@DeleteMapping("/users/{id}")
|
||||
public ApiResponse<Void> deleteUser(HttpServletRequest request, @PathVariable Long id) {
|
||||
check(AuthContext.getUser(request));
|
||||
mallService.adminDeleteUser(id);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@GetMapping("/banners")
|
||||
public ApiResponse<List<Banner>> banners(HttpServletRequest request) {
|
||||
check(AuthContext.getUser(request));
|
||||
return ApiResponse.ok(mallService.adminBanners());
|
||||
}
|
||||
|
||||
@PostMapping("/banners")
|
||||
public ApiResponse<Banner> saveBanner(HttpServletRequest request, @RequestBody Banner banner) {
|
||||
check(AuthContext.getUser(request));
|
||||
return ApiResponse.ok(mallService.adminSaveBanner(banner));
|
||||
}
|
||||
|
||||
@DeleteMapping("/banners/{id}")
|
||||
public ApiResponse<Void> deleteBanner(HttpServletRequest request, @PathVariable Long id) {
|
||||
check(AuthContext.getUser(request));
|
||||
mallService.adminDeleteBanner(id);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@GetMapping("/products")
|
||||
public ApiResponse<List<Product>> products(HttpServletRequest request) {
|
||||
check(AuthContext.getUser(request));
|
||||
return ApiResponse.ok(mallService.adminProducts());
|
||||
}
|
||||
|
||||
@GetMapping("/products/views")
|
||||
public ApiResponse<List<Map<String, Object>>> productViews(HttpServletRequest request) {
|
||||
check(AuthContext.getUser(request));
|
||||
return ApiResponse.ok(mallService.adminProductViews());
|
||||
}
|
||||
|
||||
@PostMapping("/products")
|
||||
public ApiResponse<Product> saveProduct(HttpServletRequest request, @RequestBody Product product) {
|
||||
check(AuthContext.getUser(request));
|
||||
return ApiResponse.ok(mallService.adminSaveProduct(product));
|
||||
}
|
||||
|
||||
@PutMapping("/products/{id}/approve")
|
||||
public ApiResponse<Product> approveProduct(HttpServletRequest request, @PathVariable Long id, @RequestBody Map<String, Object> body) {
|
||||
check(AuthContext.getUser(request));
|
||||
boolean approved = Boolean.parseBoolean(String.valueOf(body.getOrDefault("approved", true)));
|
||||
return ApiResponse.ok(mallService.adminApproveProduct(id, approved));
|
||||
}
|
||||
|
||||
@DeleteMapping("/products/{id}")
|
||||
public ApiResponse<Void> deleteProduct(HttpServletRequest request, @PathVariable Long id) {
|
||||
check(AuthContext.getUser(request));
|
||||
mallService.adminDeleteProduct(id);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@GetMapping("/reviews")
|
||||
public ApiResponse<List<Map<String, Object>>> reviews(HttpServletRequest request) {
|
||||
check(AuthContext.getUser(request));
|
||||
return ApiResponse.ok(mallService.adminReviews());
|
||||
}
|
||||
|
||||
@GetMapping("/logistics")
|
||||
public ApiResponse<List<Map<String, Object>>> logistics(HttpServletRequest request) {
|
||||
check(AuthContext.getUser(request));
|
||||
return ApiResponse.ok(mallService.adminLogistics());
|
||||
}
|
||||
|
||||
@GetMapping("/inventory")
|
||||
public ApiResponse<List<Map<String, Object>>> inventory(HttpServletRequest request) {
|
||||
check(AuthContext.getUser(request));
|
||||
return ApiResponse.ok(mallService.adminInventory());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.maternalmall.controller;
|
||||
|
||||
import com.maternalmall.common.ApiResponse;
|
||||
import com.maternalmall.config.AuthContext;
|
||||
import com.maternalmall.domain.User;
|
||||
import com.maternalmall.repository.UserRepository;
|
||||
import com.maternalmall.service.AuthService;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/auth")
|
||||
public class AuthController {
|
||||
private final AuthService authService;
|
||||
private final UserRepository userRepository;
|
||||
|
||||
public AuthController(AuthService authService, UserRepository userRepository) {
|
||||
this.authService = authService;
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
@PostMapping("/register")
|
||||
public ApiResponse<Map<String, Object>> register(@RequestBody Map<String, String> body) {
|
||||
return ApiResponse.ok(authService.register(body.get("username"), body.get("password"), body.getOrDefault("role", "CUSTOMER")));
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
public ApiResponse<Map<String, Object>> login(@RequestBody Map<String, String> body) {
|
||||
return ApiResponse.ok(authService.login(body.get("username"), body.get("password")));
|
||||
}
|
||||
|
||||
@GetMapping("/me")
|
||||
public ApiResponse<User> me(HttpServletRequest request) {
|
||||
return ApiResponse.ok(AuthContext.getUser(request));
|
||||
}
|
||||
|
||||
@PutMapping("/me")
|
||||
public ApiResponse<User> updateMe(HttpServletRequest request, @RequestBody Map<String, String> body) {
|
||||
User user = AuthContext.getUser(request);
|
||||
user.setNickname(body.getOrDefault("nickname", user.getNickname()));
|
||||
user.setPhone(body.getOrDefault("phone", user.getPhone()));
|
||||
user.setAddress(body.getOrDefault("address", user.getAddress()));
|
||||
return ApiResponse.ok(userRepository.save(user));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package com.maternalmall.controller;
|
||||
|
||||
import com.maternalmall.common.ApiResponse;
|
||||
import com.maternalmall.config.AuthContext;
|
||||
import com.maternalmall.domain.*;
|
||||
import com.maternalmall.service.MallService;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/customer")
|
||||
public class CustomerController {
|
||||
private final MallService mallService;
|
||||
|
||||
public CustomerController(MallService mallService) {
|
||||
this.mallService = mallService;
|
||||
}
|
||||
|
||||
@GetMapping("/cart")
|
||||
public ApiResponse<List<CartItem>> cart(HttpServletRequest request) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.CUSTOMER);
|
||||
return ApiResponse.ok(mallService.cartList(user.getId()));
|
||||
}
|
||||
|
||||
@GetMapping("/cart/views")
|
||||
public ApiResponse<List<Map<String, Object>>> cartViews(HttpServletRequest request) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.CUSTOMER);
|
||||
return ApiResponse.ok(mallService.cartViews(user.getId()));
|
||||
}
|
||||
|
||||
@PostMapping("/cart")
|
||||
public ApiResponse<CartItem> addCart(HttpServletRequest request, @RequestBody Map<String, Object> body) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.CUSTOMER);
|
||||
return ApiResponse.ok(mallService.addCart(user.getId(), Long.valueOf(body.get("productId").toString()), Integer.valueOf(body.get("quantity").toString())));
|
||||
}
|
||||
|
||||
@DeleteMapping("/cart/{productId}")
|
||||
public ApiResponse<Void> removeCart(HttpServletRequest request, @PathVariable Long productId) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.CUSTOMER);
|
||||
mallService.removeCart(user.getId(), productId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@GetMapping("/favorites")
|
||||
public ApiResponse<List<Favorite>> favorites(HttpServletRequest request) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.CUSTOMER);
|
||||
return ApiResponse.ok(mallService.favoriteList(user.getId()));
|
||||
}
|
||||
|
||||
@GetMapping("/favorites/views")
|
||||
public ApiResponse<List<Map<String, Object>>> favoriteViews(HttpServletRequest request) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.CUSTOMER);
|
||||
return ApiResponse.ok(mallService.favoriteViews(user.getId()));
|
||||
}
|
||||
|
||||
@PostMapping("/favorites")
|
||||
public ApiResponse<Favorite> addFavorite(HttpServletRequest request, @RequestBody Map<String, Object> body) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.CUSTOMER);
|
||||
return ApiResponse.ok(mallService.addFavorite(user.getId(), Long.valueOf(body.get("productId").toString())));
|
||||
}
|
||||
|
||||
@DeleteMapping("/favorites/{productId}")
|
||||
public ApiResponse<Void> removeFavorite(HttpServletRequest request, @PathVariable Long productId) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.CUSTOMER);
|
||||
mallService.removeFavorite(user.getId(), productId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/orders/checkout")
|
||||
public ApiResponse<Orders> checkout(HttpServletRequest request, @RequestBody Map<String, String> body) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.CUSTOMER);
|
||||
return ApiResponse.ok(mallService.checkout(user.getId(), body.get("address")));
|
||||
}
|
||||
|
||||
@PostMapping("/orders/buy-now")
|
||||
public ApiResponse<Orders> buyNow(HttpServletRequest request, @RequestBody Map<String, Object> body) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.CUSTOMER);
|
||||
Long productId = Long.valueOf(body.get("productId").toString());
|
||||
Integer quantity = Integer.valueOf(String.valueOf(body.getOrDefault("quantity", 1)));
|
||||
String address = String.valueOf(body.getOrDefault("address", ""));
|
||||
return ApiResponse.ok(mallService.buyNow(user.getId(), productId, quantity, address));
|
||||
}
|
||||
|
||||
@GetMapping("/orders")
|
||||
public ApiResponse<List<Orders>> orders(HttpServletRequest request) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.CUSTOMER);
|
||||
return ApiResponse.ok(mallService.customerOrders(user.getId()));
|
||||
}
|
||||
|
||||
@GetMapping("/orders/{orderId}/items")
|
||||
public ApiResponse<List<OrderItem>> orderItems(HttpServletRequest request, @PathVariable Long orderId) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.CUSTOMER);
|
||||
return ApiResponse.ok(mallService.customerOrderItems(user.getId(), orderId));
|
||||
}
|
||||
|
||||
@PutMapping("/orders/{orderId}/address")
|
||||
public ApiResponse<Orders> updateAddress(HttpServletRequest request, @PathVariable Long orderId, @RequestBody Map<String, String> body) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.CUSTOMER);
|
||||
return ApiResponse.ok(mallService.customerUpdateAddress(user.getId(), orderId, body.get("address")));
|
||||
}
|
||||
|
||||
@PutMapping("/orders/{orderId}/refund")
|
||||
public ApiResponse<Orders> refund(HttpServletRequest request, @PathVariable Long orderId, @RequestBody Map<String, String> body) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.CUSTOMER);
|
||||
return ApiResponse.ok(mallService.customerRefund(user.getId(), orderId, body.get("reason")));
|
||||
}
|
||||
|
||||
@DeleteMapping("/orders/{orderId}")
|
||||
public ApiResponse<Void> deleteOrder(HttpServletRequest request, @PathVariable Long orderId) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.CUSTOMER);
|
||||
mallService.customerDeleteOrder(user.getId(), orderId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@GetMapping("/orders/{orderId}/logistics")
|
||||
public ApiResponse<List<LogisticsRecord>> logistics(HttpServletRequest request, @PathVariable Long orderId) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.CUSTOMER);
|
||||
return ApiResponse.ok(mallService.logisticsOfOrder(user.getId(), orderId));
|
||||
}
|
||||
|
||||
@PostMapping("/reviews")
|
||||
public ApiResponse<Review> review(HttpServletRequest request, @RequestBody Map<String, Object> body) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.CUSTOMER);
|
||||
return ApiResponse.ok(mallService.addReview(
|
||||
user.getId(),
|
||||
Long.valueOf(body.get("orderId").toString()),
|
||||
Long.valueOf(body.get("productId").toString()),
|
||||
Integer.valueOf(body.get("rating").toString()),
|
||||
body.get("content").toString()));
|
||||
}
|
||||
|
||||
@PostMapping("/merchant-applications")
|
||||
public ApiResponse<MerchantApplication> applyMerchant(HttpServletRequest request, @RequestBody Map<String, String> body) {
|
||||
User user = AuthContext.getUser(request);
|
||||
return ApiResponse.ok(mallService.applyMerchant(user.getId(), body.getOrDefault("qualification", "")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.maternalmall.controller;
|
||||
|
||||
import com.maternalmall.common.ApiResponse;
|
||||
import com.maternalmall.config.AuthContext;
|
||||
import com.maternalmall.domain.*;
|
||||
import com.maternalmall.service.MallService;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/merchant")
|
||||
public class MerchantController {
|
||||
private final MallService mallService;
|
||||
|
||||
public MerchantController(MallService mallService) {
|
||||
this.mallService = mallService;
|
||||
}
|
||||
|
||||
@GetMapping("/overview")
|
||||
public ApiResponse<Map<String, Object>> overview(HttpServletRequest request) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.MERCHANT);
|
||||
return ApiResponse.ok(mallService.merchantOverview(user.getId()));
|
||||
}
|
||||
|
||||
@GetMapping("/products")
|
||||
public ApiResponse<List<Product>> products(HttpServletRequest request) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.MERCHANT);
|
||||
return ApiResponse.ok(mallService.merchantProducts(user.getId()));
|
||||
}
|
||||
|
||||
@PostMapping("/products")
|
||||
public ApiResponse<Product> saveProduct(HttpServletRequest request, @RequestBody Product product) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.MERCHANT);
|
||||
return ApiResponse.ok(mallService.merchantSaveProduct(user.getId(), product));
|
||||
}
|
||||
|
||||
@DeleteMapping("/products/{id}")
|
||||
public ApiResponse<Void> deleteProduct(HttpServletRequest request, @PathVariable Long id) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.MERCHANT);
|
||||
mallService.merchantDeleteProduct(user.getId(), id);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@GetMapping("/orders")
|
||||
public ApiResponse<List<Orders>> orders(HttpServletRequest request) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.MERCHANT);
|
||||
return ApiResponse.ok(mallService.merchantOrders(user.getId()));
|
||||
}
|
||||
|
||||
@PutMapping("/orders/{id}/ship")
|
||||
public ApiResponse<Orders> ship(HttpServletRequest request, @PathVariable Long id, @RequestBody Map<String, String> body) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.MERCHANT);
|
||||
return ApiResponse.ok(mallService.merchantShip(user.getId(), id, body.getOrDefault("note", "已发货")));
|
||||
}
|
||||
|
||||
@PutMapping("/orders/{id}/refund")
|
||||
public ApiResponse<Orders> refund(HttpServletRequest request, @PathVariable Long id, @RequestBody Map<String, Object> body) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.MERCHANT);
|
||||
return ApiResponse.ok(mallService.merchantProcessRefund(user.getId(), id, Boolean.parseBoolean(body.get("agree").toString())));
|
||||
}
|
||||
|
||||
@GetMapping("/reviews")
|
||||
public ApiResponse<List<Map<String, Object>>> reviews(HttpServletRequest request) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.MERCHANT);
|
||||
return ApiResponse.ok(mallService.merchantReviews(user.getId()));
|
||||
}
|
||||
|
||||
@GetMapping("/logistics")
|
||||
public ApiResponse<List<Map<String, Object>>> logistics(HttpServletRequest request) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.MERCHANT);
|
||||
return ApiResponse.ok(mallService.merchantLogistics(user.getId()));
|
||||
}
|
||||
|
||||
@GetMapping("/inventory")
|
||||
public ApiResponse<List<Map<String, Object>>> inventory(HttpServletRequest request) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.MERCHANT);
|
||||
return ApiResponse.ok(mallService.merchantInventory(user.getId()));
|
||||
}
|
||||
|
||||
@DeleteMapping("/inventory/{id}")
|
||||
public ApiResponse<Void> deleteInventory(HttpServletRequest request, @PathVariable Long id) {
|
||||
User user = AuthContext.getUser(request);
|
||||
mallService.requireRole(user, UserRole.MERCHANT);
|
||||
mallService.merchantDeleteInventory(user.getId(), id);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.maternalmall.controller;
|
||||
|
||||
import com.maternalmall.common.ApiResponse;
|
||||
import com.maternalmall.domain.Banner;
|
||||
import com.maternalmall.domain.Product;
|
||||
import com.maternalmall.domain.Review;
|
||||
import com.maternalmall.repository.ReviewRepository;
|
||||
import com.maternalmall.service.MallService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/public")
|
||||
public class PublicController {
|
||||
private final MallService mallService;
|
||||
private final ReviewRepository reviewRepository;
|
||||
|
||||
public PublicController(MallService mallService, ReviewRepository reviewRepository) {
|
||||
this.mallService = mallService;
|
||||
this.reviewRepository = reviewRepository;
|
||||
}
|
||||
|
||||
@GetMapping("/products")
|
||||
public ApiResponse<List<Product>> products(@RequestParam(required = false) String keyword) {
|
||||
return ApiResponse.ok(mallService.searchProducts(keyword));
|
||||
}
|
||||
|
||||
@GetMapping("/products/{id}")
|
||||
public ApiResponse<Product> product(@PathVariable Long id) {
|
||||
return ApiResponse.ok(mallService.getProduct(id));
|
||||
}
|
||||
|
||||
@GetMapping("/products/{id}/reviews")
|
||||
public ApiResponse<List<Review>> reviews(@PathVariable Long id) {
|
||||
return ApiResponse.ok(reviewRepository.findByProductId(id));
|
||||
}
|
||||
|
||||
@GetMapping("/banners")
|
||||
public ApiResponse<List<Banner>> banners() {
|
||||
return ApiResponse.ok(mallService.banners());
|
||||
}
|
||||
}
|
||||
25
backend/src/main/java/com/maternalmall/domain/Banner.java
Normal file
25
backend/src/main/java/com/maternalmall/domain/Banner.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package com.maternalmall.domain;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "banner")
|
||||
public class Banner {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false, length = 255)
|
||||
private String imageUrl;
|
||||
|
||||
@Column(length = 255)
|
||||
private String linkUrl;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Integer sortNo = 0;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Boolean enabled = true;
|
||||
}
|
||||
22
backend/src/main/java/com/maternalmall/domain/CartItem.java
Normal file
22
backend/src/main/java/com/maternalmall/domain/CartItem.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package com.maternalmall.domain;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "cart_item", uniqueConstraints = @UniqueConstraint(columnNames = {"customerId", "productId"}))
|
||||
public class CartItem {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long customerId;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long productId;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Integer quantity;
|
||||
}
|
||||
19
backend/src/main/java/com/maternalmall/domain/Favorite.java
Normal file
19
backend/src/main/java/com/maternalmall/domain/Favorite.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.maternalmall.domain;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "favorite", uniqueConstraints = @UniqueConstraint(columnNames = {"customerId", "productId"}))
|
||||
public class Favorite {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long customerId;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long productId;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.maternalmall.domain;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "inventory_record")
|
||||
public class InventoryRecord {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long productId;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long merchantId;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Integer changeQty;
|
||||
|
||||
@Column(length = 255)
|
||||
private String note;
|
||||
|
||||
@CreationTimestamp
|
||||
private LocalDateTime createdAt;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.maternalmall.domain;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "logistics_record")
|
||||
public class LogisticsRecord {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long orderId;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long merchantId;
|
||||
|
||||
@Column(length = 255, nullable = false)
|
||||
private String status;
|
||||
|
||||
@Column(length = 255)
|
||||
private String note;
|
||||
|
||||
@CreationTimestamp
|
||||
private LocalDateTime createdAt;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.maternalmall.domain;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
import org.hibernate.annotations.UpdateTimestamp;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "merchant_application")
|
||||
public class MerchantApplication {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long userId;
|
||||
|
||||
@Column(length = 255)
|
||||
private String qualification;
|
||||
|
||||
@Column(length = 30, nullable = false)
|
||||
private String status = "PENDING";
|
||||
|
||||
@Column(length = 255)
|
||||
private String remark;
|
||||
|
||||
@CreationTimestamp
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@UpdateTimestamp
|
||||
private LocalDateTime updatedAt;
|
||||
}
|
||||
30
backend/src/main/java/com/maternalmall/domain/OrderItem.java
Normal file
30
backend/src/main/java/com/maternalmall/domain/OrderItem.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.maternalmall.domain;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "order_item")
|
||||
public class OrderItem {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long orderId;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long productId;
|
||||
|
||||
@Column(nullable = false, length = 120)
|
||||
private String productName;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Integer quantity;
|
||||
|
||||
@Column(nullable = false, precision = 10, scale = 2)
|
||||
private BigDecimal unitPrice;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.maternalmall.domain;
|
||||
|
||||
public enum OrderStatus {
|
||||
PENDING_PAYMENT,
|
||||
PAID,
|
||||
SHIPPED,
|
||||
COMPLETED,
|
||||
REFUND_REQUESTED,
|
||||
REFUNDED,
|
||||
CANCELLED
|
||||
}
|
||||
49
backend/src/main/java/com/maternalmall/domain/Orders.java
Normal file
49
backend/src/main/java/com/maternalmall/domain/Orders.java
Normal file
@@ -0,0 +1,49 @@
|
||||
package com.maternalmall.domain;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
import org.hibernate.annotations.UpdateTimestamp;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "orders")
|
||||
public class Orders {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false, unique = true, length = 50)
|
||||
private String orderNo;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long customerId;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long merchantId;
|
||||
|
||||
@Column(nullable = false, precision = 10, scale = 2)
|
||||
private BigDecimal totalAmount;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(nullable = false, length = 30)
|
||||
private OrderStatus status;
|
||||
|
||||
@Column(length = 255)
|
||||
private String address;
|
||||
|
||||
@Column(length = 255)
|
||||
private String logisticsInfo;
|
||||
|
||||
@Column(length = 255)
|
||||
private String refundReason;
|
||||
|
||||
@CreationTimestamp
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@UpdateTimestamp
|
||||
private LocalDateTime updatedAt;
|
||||
}
|
||||
48
backend/src/main/java/com/maternalmall/domain/Product.java
Normal file
48
backend/src/main/java/com/maternalmall/domain/Product.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package com.maternalmall.domain;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
import org.hibernate.annotations.UpdateTimestamp;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "product")
|
||||
public class Product {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false, length = 120)
|
||||
private String name;
|
||||
|
||||
@Column(length = 50)
|
||||
private String category;
|
||||
|
||||
@Column(length = 1000)
|
||||
private String description;
|
||||
|
||||
@Column(nullable = false, precision = 10, scale = 2)
|
||||
private BigDecimal price;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Integer stock;
|
||||
|
||||
@Column(length = 255)
|
||||
private String imageUrl;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long merchantId;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Boolean approved = false;
|
||||
|
||||
@CreationTimestamp
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@UpdateTimestamp
|
||||
private LocalDateTime updatedAt;
|
||||
}
|
||||
34
backend/src/main/java/com/maternalmall/domain/Review.java
Normal file
34
backend/src/main/java/com/maternalmall/domain/Review.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package com.maternalmall.domain;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "review")
|
||||
public class Review {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long orderId;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long productId;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long customerId;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Integer rating;
|
||||
|
||||
@Column(length = 1000)
|
||||
private String content;
|
||||
|
||||
@CreationTimestamp
|
||||
private LocalDateTime createdAt;
|
||||
}
|
||||
48
backend/src/main/java/com/maternalmall/domain/User.java
Normal file
48
backend/src/main/java/com/maternalmall/domain/User.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package com.maternalmall.domain;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
import org.hibernate.annotations.UpdateTimestamp;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "users")
|
||||
public class User {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(unique = true, nullable = false, length = 50)
|
||||
private String username;
|
||||
|
||||
@Column(nullable = false, length = 100)
|
||||
private String password;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(nullable = false, length = 20)
|
||||
private UserRole role;
|
||||
|
||||
@Column(length = 50)
|
||||
private String nickname;
|
||||
|
||||
@Column(length = 20)
|
||||
private String phone;
|
||||
|
||||
@Column(length = 255)
|
||||
private String address;
|
||||
|
||||
@Column(length = 100)
|
||||
private String token;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Boolean enabled = true;
|
||||
|
||||
@CreationTimestamp
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@UpdateTimestamp
|
||||
private LocalDateTime updatedAt;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.maternalmall.domain;
|
||||
|
||||
public enum UserRole {
|
||||
CUSTOMER,
|
||||
MERCHANT,
|
||||
ADMIN
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.maternalmall.repository;
|
||||
|
||||
import com.maternalmall.domain.Banner;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface BannerRepository extends JpaRepository<Banner, Long> {
|
||||
List<Banner> findByEnabledTrueOrderBySortNoAsc();
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.maternalmall.repository;
|
||||
|
||||
import com.maternalmall.domain.CartItem;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface CartItemRepository extends JpaRepository<CartItem, Long> {
|
||||
List<CartItem> findByCustomerId(Long customerId);
|
||||
Optional<CartItem> findByCustomerIdAndProductId(Long customerId, Long productId);
|
||||
|
||||
@Modifying
|
||||
@Transactional
|
||||
void deleteByCustomerIdAndProductId(Long customerId, Long productId);
|
||||
|
||||
@Modifying
|
||||
@Transactional
|
||||
void deleteByCustomerId(Long customerId);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.maternalmall.repository;
|
||||
|
||||
import com.maternalmall.domain.Favorite;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface FavoriteRepository extends JpaRepository<Favorite, Long> {
|
||||
List<Favorite> findByCustomerId(Long customerId);
|
||||
Optional<Favorite> findByCustomerIdAndProductId(Long customerId, Long productId);
|
||||
|
||||
@Modifying
|
||||
@Transactional
|
||||
void deleteByCustomerIdAndProductId(Long customerId, Long productId);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.maternalmall.repository;
|
||||
|
||||
import com.maternalmall.domain.InventoryRecord;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface InventoryRecordRepository extends JpaRepository<InventoryRecord, Long> {
|
||||
List<InventoryRecord> findByMerchantId(Long merchantId);
|
||||
List<InventoryRecord> findByProductId(Long productId);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.maternalmall.repository;
|
||||
|
||||
import com.maternalmall.domain.LogisticsRecord;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface LogisticsRecordRepository extends JpaRepository<LogisticsRecord, Long> {
|
||||
List<LogisticsRecord> findByOrderId(Long orderId);
|
||||
List<LogisticsRecord> findByMerchantId(Long merchantId);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.maternalmall.repository;
|
||||
|
||||
import com.maternalmall.domain.MerchantApplication;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface MerchantApplicationRepository extends JpaRepository<MerchantApplication, Long> {
|
||||
List<MerchantApplication> findByStatus(String status);
|
||||
boolean existsByUserIdAndStatus(Long userId, String status);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.maternalmall.repository;
|
||||
|
||||
import com.maternalmall.domain.OrderItem;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface OrderItemRepository extends JpaRepository<OrderItem, Long> {
|
||||
List<OrderItem> findByOrderId(Long orderId);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.maternalmall.repository;
|
||||
|
||||
import com.maternalmall.domain.OrderStatus;
|
||||
import com.maternalmall.domain.Orders;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface OrdersRepository extends JpaRepository<Orders, Long> {
|
||||
List<Orders> findByCustomerId(Long customerId);
|
||||
List<Orders> findByMerchantId(Long merchantId);
|
||||
List<Orders> findByStatus(OrderStatus status);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.maternalmall.repository;
|
||||
|
||||
import com.maternalmall.domain.Product;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ProductRepository extends JpaRepository<Product, Long> {
|
||||
List<Product> findByApprovedTrueAndNameContainingIgnoreCase(String name);
|
||||
List<Product> findByMerchantId(Long merchantId);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.maternalmall.repository;
|
||||
|
||||
import com.maternalmall.domain.Review;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ReviewRepository extends JpaRepository<Review, Long> {
|
||||
List<Review> findByProductId(Long productId);
|
||||
List<Review> findByCustomerId(Long customerId);
|
||||
boolean existsByOrderIdAndProductIdAndCustomerId(Long orderId, Long productId, Long customerId);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.maternalmall.repository;
|
||||
|
||||
import com.maternalmall.domain.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface UserRepository extends JpaRepository<User, Long> {
|
||||
Optional<User> findByUsername(String username);
|
||||
Optional<User> findByToken(String token);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.maternalmall.service;
|
||||
|
||||
import com.maternalmall.common.BizException;
|
||||
import com.maternalmall.domain.User;
|
||||
import com.maternalmall.domain.UserRole;
|
||||
import com.maternalmall.repository.UserRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class AuthService {
|
||||
private final UserRepository userRepository;
|
||||
|
||||
public AuthService(UserRepository userRepository) {
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
public Map<String, Object> register(String username, String password, String role) {
|
||||
username = username == null ? "" : username.trim();
|
||||
password = password == null ? "" : password.trim();
|
||||
if (username.isEmpty()) {
|
||||
throw new BizException("用户名不能为空");
|
||||
}
|
||||
if (password.isEmpty()) {
|
||||
throw new BizException("密码不能为空");
|
||||
}
|
||||
userRepository.findByUsername(username).ifPresent(u -> {
|
||||
throw new BizException("账号已存在");
|
||||
});
|
||||
if (role != null && !role.isBlank() && !"CUSTOMER".equalsIgnoreCase(role)) {
|
||||
throw new BizException("仅支持注册顾客账号,商家需提交入驻申请");
|
||||
}
|
||||
User user = new User();
|
||||
user.setUsername(username);
|
||||
user.setPassword(password);
|
||||
user.setRole(UserRole.CUSTOMER);
|
||||
user.setNickname(username);
|
||||
userRepository.save(user);
|
||||
return Map.of("userId", user.getId());
|
||||
}
|
||||
|
||||
public Map<String, Object> login(String username, String password) {
|
||||
User user = userRepository.findByUsername(username).orElseThrow(() -> new BizException("用户不存在"));
|
||||
if (!user.getPassword().equals(password)) {
|
||||
throw new BizException("密码错误");
|
||||
}
|
||||
if (!Boolean.TRUE.equals(user.getEnabled())) {
|
||||
throw new BizException("账号已被禁用,请联系管理员");
|
||||
}
|
||||
String token = UUID.randomUUID().toString().replace("-", "");
|
||||
user.setToken(token);
|
||||
userRepository.save(user);
|
||||
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("token", token);
|
||||
data.put("id", user.getId());
|
||||
data.put("username", user.getUsername());
|
||||
data.put("role", user.getRole());
|
||||
data.put("nickname", user.getNickname());
|
||||
return data;
|
||||
}
|
||||
}
|
||||
887
backend/src/main/java/com/maternalmall/service/MallService.java
Normal file
887
backend/src/main/java/com/maternalmall/service/MallService.java
Normal file
@@ -0,0 +1,887 @@
|
||||
package com.maternalmall.service;
|
||||
|
||||
import com.maternalmall.common.BizException;
|
||||
import com.maternalmall.domain.*;
|
||||
import com.maternalmall.repository.*;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
public class MallService {
|
||||
private final ProductRepository productRepository;
|
||||
private final CartItemRepository cartItemRepository;
|
||||
private final FavoriteRepository favoriteRepository;
|
||||
private final OrdersRepository ordersRepository;
|
||||
private final OrderItemRepository orderItemRepository;
|
||||
private final ReviewRepository reviewRepository;
|
||||
private final LogisticsRecordRepository logisticsRecordRepository;
|
||||
private final InventoryRecordRepository inventoryRecordRepository;
|
||||
private final MerchantApplicationRepository merchantApplicationRepository;
|
||||
private final BannerRepository bannerRepository;
|
||||
private final UserRepository userRepository;
|
||||
|
||||
public MallService(ProductRepository productRepository,
|
||||
CartItemRepository cartItemRepository,
|
||||
FavoriteRepository favoriteRepository,
|
||||
OrdersRepository ordersRepository,
|
||||
OrderItemRepository orderItemRepository,
|
||||
ReviewRepository reviewRepository,
|
||||
LogisticsRecordRepository logisticsRecordRepository,
|
||||
InventoryRecordRepository inventoryRecordRepository,
|
||||
MerchantApplicationRepository merchantApplicationRepository,
|
||||
BannerRepository bannerRepository,
|
||||
UserRepository userRepository) {
|
||||
this.productRepository = productRepository;
|
||||
this.cartItemRepository = cartItemRepository;
|
||||
this.favoriteRepository = favoriteRepository;
|
||||
this.ordersRepository = ordersRepository;
|
||||
this.orderItemRepository = orderItemRepository;
|
||||
this.reviewRepository = reviewRepository;
|
||||
this.logisticsRecordRepository = logisticsRecordRepository;
|
||||
this.inventoryRecordRepository = inventoryRecordRepository;
|
||||
this.merchantApplicationRepository = merchantApplicationRepository;
|
||||
this.bannerRepository = bannerRepository;
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
public void requireRole(User user, UserRole role) {
|
||||
if (user.getRole() != role) {
|
||||
throw new BizException("无权限操作");
|
||||
}
|
||||
}
|
||||
|
||||
public List<Product> searchProducts(String keyword) {
|
||||
return productRepository.findByApprovedTrueAndNameContainingIgnoreCase(keyword == null ? "" : keyword);
|
||||
}
|
||||
|
||||
public Product getProduct(Long id) {
|
||||
return productRepository.findById(id).orElseThrow(() -> new BizException("商品不存在"));
|
||||
}
|
||||
|
||||
public List<Banner> banners() {
|
||||
return bannerRepository.findByEnabledTrueOrderBySortNoAsc();
|
||||
}
|
||||
|
||||
public List<CartItem> cartList(Long customerId) {
|
||||
return cartItemRepository.findByCustomerId(customerId);
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> cartViews(Long customerId) {
|
||||
List<CartItem> items = cartItemRepository.findByCustomerId(customerId);
|
||||
List<Map<String, Object>> views = new ArrayList<>();
|
||||
for (CartItem item : items) {
|
||||
Product p = getProduct(item.getProductId());
|
||||
Map<String, Object> row = new HashMap<>();
|
||||
row.put("productId", p.getId());
|
||||
row.put("productName", p.getName());
|
||||
row.put("category", p.getCategory());
|
||||
row.put("imageUrl", p.getImageUrl());
|
||||
row.put("unitPrice", p.getPrice());
|
||||
row.put("quantity", item.getQuantity());
|
||||
row.put("subtotal", p.getPrice().multiply(BigDecimal.valueOf(item.getQuantity())));
|
||||
row.put("stock", p.getStock());
|
||||
views.add(row);
|
||||
}
|
||||
return views;
|
||||
}
|
||||
|
||||
public CartItem addCart(Long customerId, Long productId, Integer quantity) {
|
||||
Product product = getProduct(productId);
|
||||
if (!product.getApproved()) {
|
||||
throw new BizException("商品未上架");
|
||||
}
|
||||
CartItem item = cartItemRepository.findByCustomerIdAndProductId(customerId, productId).orElseGet(CartItem::new);
|
||||
item.setCustomerId(customerId);
|
||||
item.setProductId(productId);
|
||||
item.setQuantity((item.getQuantity() == null ? 0 : item.getQuantity()) + quantity);
|
||||
return cartItemRepository.save(item);
|
||||
}
|
||||
|
||||
public void removeCart(Long customerId, Long productId) {
|
||||
cartItemRepository.deleteByCustomerIdAndProductId(customerId, productId);
|
||||
}
|
||||
|
||||
public List<Favorite> favoriteList(Long customerId) {
|
||||
return favoriteRepository.findByCustomerId(customerId);
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> favoriteViews(Long customerId) {
|
||||
List<Favorite> favorites = favoriteRepository.findByCustomerId(customerId);
|
||||
List<Map<String, Object>> views = new ArrayList<>();
|
||||
for (Favorite favorite : favorites) {
|
||||
Product p = getProduct(favorite.getProductId());
|
||||
Map<String, Object> row = new HashMap<>();
|
||||
row.put("productId", p.getId());
|
||||
row.put("productName", p.getName());
|
||||
row.put("category", p.getCategory());
|
||||
row.put("imageUrl", p.getImageUrl());
|
||||
row.put("unitPrice", p.getPrice());
|
||||
row.put("stock", p.getStock());
|
||||
views.add(row);
|
||||
}
|
||||
return views;
|
||||
}
|
||||
|
||||
public Favorite addFavorite(Long customerId, Long productId) {
|
||||
favoriteRepository.findByCustomerIdAndProductId(customerId, productId).ifPresent(f -> {
|
||||
throw new BizException("已收藏");
|
||||
});
|
||||
Favorite favorite = new Favorite();
|
||||
favorite.setCustomerId(customerId);
|
||||
favorite.setProductId(productId);
|
||||
return favoriteRepository.save(favorite);
|
||||
}
|
||||
|
||||
public void removeFavorite(Long customerId, Long productId) {
|
||||
favoriteRepository.deleteByCustomerIdAndProductId(customerId, productId);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Orders checkout(Long customerId, String address) {
|
||||
List<CartItem> cartItems = cartItemRepository.findByCustomerId(customerId);
|
||||
if (cartItems.isEmpty()) {
|
||||
throw new BizException("购物车为空");
|
||||
}
|
||||
Long merchantId = null;
|
||||
BigDecimal total = BigDecimal.ZERO;
|
||||
Orders order = new Orders();
|
||||
order.setOrderNo("MM" + System.currentTimeMillis());
|
||||
order.setCustomerId(customerId);
|
||||
order.setStatus(OrderStatus.PAID);
|
||||
order.setAddress(address);
|
||||
|
||||
for (CartItem cartItem : cartItems) {
|
||||
Product product = getProduct(cartItem.getProductId());
|
||||
if (product.getStock() < cartItem.getQuantity()) {
|
||||
throw new BizException("库存不足: " + product.getName());
|
||||
}
|
||||
if (merchantId == null) {
|
||||
merchantId = product.getMerchantId();
|
||||
} else if (!merchantId.equals(product.getMerchantId())) {
|
||||
throw new BizException("当前基础版本仅支持单商家结算");
|
||||
}
|
||||
product.setStock(product.getStock() - cartItem.getQuantity());
|
||||
productRepository.save(product);
|
||||
|
||||
InventoryRecord record = new InventoryRecord();
|
||||
record.setMerchantId(product.getMerchantId());
|
||||
record.setProductId(product.getId());
|
||||
record.setChangeQty(-cartItem.getQuantity());
|
||||
record.setNote("订单扣减库存");
|
||||
inventoryRecordRepository.save(record);
|
||||
|
||||
BigDecimal line = product.getPrice().multiply(BigDecimal.valueOf(cartItem.getQuantity()));
|
||||
total = total.add(line);
|
||||
}
|
||||
order.setMerchantId(merchantId);
|
||||
order.setTotalAmount(total);
|
||||
ordersRepository.save(order);
|
||||
|
||||
for (CartItem cartItem : cartItems) {
|
||||
Product product = getProduct(cartItem.getProductId());
|
||||
OrderItem item = new OrderItem();
|
||||
item.setOrderId(order.getId());
|
||||
item.setProductId(product.getId());
|
||||
item.setProductName(product.getName());
|
||||
item.setQuantity(cartItem.getQuantity());
|
||||
item.setUnitPrice(product.getPrice());
|
||||
orderItemRepository.save(item);
|
||||
}
|
||||
cartItemRepository.deleteByCustomerId(customerId);
|
||||
return order;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Orders buyNow(Long customerId, Long productId, Integer quantity, String address) {
|
||||
if (quantity == null || quantity <= 0) {
|
||||
throw new BizException("购买数量必须大于0");
|
||||
}
|
||||
Product product = getProduct(productId);
|
||||
if (!Boolean.TRUE.equals(product.getApproved())) {
|
||||
throw new BizException("商品未上架");
|
||||
}
|
||||
if (product.getStock() < quantity) {
|
||||
throw new BizException("库存不足: " + product.getName());
|
||||
}
|
||||
|
||||
product.setStock(product.getStock() - quantity);
|
||||
productRepository.save(product);
|
||||
|
||||
InventoryRecord record = new InventoryRecord();
|
||||
record.setMerchantId(product.getMerchantId());
|
||||
record.setProductId(product.getId());
|
||||
record.setChangeQty(-quantity);
|
||||
record.setNote("立即购买扣减库存");
|
||||
inventoryRecordRepository.save(record);
|
||||
|
||||
Orders order = new Orders();
|
||||
order.setOrderNo("MM" + System.currentTimeMillis());
|
||||
order.setCustomerId(customerId);
|
||||
order.setMerchantId(product.getMerchantId());
|
||||
order.setStatus(OrderStatus.PAID);
|
||||
order.setAddress(address);
|
||||
order.setTotalAmount(product.getPrice().multiply(BigDecimal.valueOf(quantity)));
|
||||
ordersRepository.save(order);
|
||||
|
||||
OrderItem item = new OrderItem();
|
||||
item.setOrderId(order.getId());
|
||||
item.setProductId(product.getId());
|
||||
item.setProductName(product.getName());
|
||||
item.setQuantity(quantity);
|
||||
item.setUnitPrice(product.getPrice());
|
||||
orderItemRepository.save(item);
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
public List<Orders> customerOrders(Long customerId) {
|
||||
return ordersRepository.findByCustomerId(customerId);
|
||||
}
|
||||
|
||||
public List<OrderItem> customerOrderItems(Long customerId, Long orderId) {
|
||||
Orders order = ordersRepository.findById(orderId).orElseThrow(() -> new BizException("订单不存在"));
|
||||
if (!order.getCustomerId().equals(customerId)) {
|
||||
throw new BizException("无权限操作");
|
||||
}
|
||||
return orderItemRepository.findByOrderId(orderId);
|
||||
}
|
||||
|
||||
public Orders customerUpdateAddress(Long customerId, Long orderId, String address) {
|
||||
Orders order = ordersRepository.findById(orderId).orElseThrow(() -> new BizException("订单不存在"));
|
||||
if (!order.getCustomerId().equals(customerId)) {
|
||||
throw new BizException("无权限操作");
|
||||
}
|
||||
if (order.getStatus() == OrderStatus.SHIPPED || order.getStatus() == OrderStatus.COMPLETED) {
|
||||
throw new BizException("该状态不可修改地址");
|
||||
}
|
||||
order.setAddress(address);
|
||||
return ordersRepository.save(order);
|
||||
}
|
||||
|
||||
public Orders customerRefund(Long customerId, Long orderId, String reason) {
|
||||
Orders order = ordersRepository.findById(orderId).orElseThrow(() -> new BizException("订单不存在"));
|
||||
if (!order.getCustomerId().equals(customerId)) {
|
||||
throw new BizException("无权限操作");
|
||||
}
|
||||
order.setStatus(OrderStatus.REFUND_REQUESTED);
|
||||
order.setRefundReason(reason);
|
||||
return ordersRepository.save(order);
|
||||
}
|
||||
|
||||
public void customerDeleteOrder(Long customerId, Long orderId) {
|
||||
Orders order = ordersRepository.findById(orderId).orElseThrow(() -> new BizException("订单不存在"));
|
||||
if (!order.getCustomerId().equals(customerId)) {
|
||||
throw new BizException("无权限操作");
|
||||
}
|
||||
if (!(order.getStatus() == OrderStatus.COMPLETED || order.getStatus() == OrderStatus.REFUNDED || order.getStatus() == OrderStatus.CANCELLED)) {
|
||||
throw new BizException("当前状态不可删除");
|
||||
}
|
||||
ordersRepository.delete(order);
|
||||
}
|
||||
|
||||
public List<LogisticsRecord> logisticsOfOrder(Long customerId, Long orderId) {
|
||||
Orders order = ordersRepository.findById(orderId).orElseThrow(() -> new BizException("订单不存在"));
|
||||
if (!order.getCustomerId().equals(customerId)) {
|
||||
throw new BizException("无权限操作");
|
||||
}
|
||||
return logisticsRecordRepository.findByOrderId(orderId);
|
||||
}
|
||||
|
||||
public Review addReview(Long customerId, Long orderId, Long productId, Integer rating, String content) {
|
||||
Orders order = ordersRepository.findById(orderId).orElseThrow(() -> new BizException("订单不存在"));
|
||||
if (!order.getCustomerId().equals(customerId)) {
|
||||
throw new BizException("无权限操作");
|
||||
}
|
||||
if (rating == null || rating < 1 || rating > 5) {
|
||||
throw new BizException("评分范围为1-5分");
|
||||
}
|
||||
if (!(order.getStatus() == OrderStatus.PAID
|
||||
|| order.getStatus() == OrderStatus.SHIPPED
|
||||
|| order.getStatus() == OrderStatus.COMPLETED
|
||||
|| order.getStatus() == OrderStatus.REFUND_REQUESTED
|
||||
|| order.getStatus() == OrderStatus.REFUNDED)) {
|
||||
throw new BizException("仅已购买商品可评价");
|
||||
}
|
||||
boolean ordered = orderItemRepository.findByOrderId(orderId)
|
||||
.stream()
|
||||
.anyMatch(i -> i.getProductId().equals(productId));
|
||||
if (!ordered) {
|
||||
throw new BizException("该商品不在订单内");
|
||||
}
|
||||
if (reviewRepository.existsByOrderIdAndProductIdAndCustomerId(orderId, productId, customerId)) {
|
||||
throw new BizException("该商品已评价");
|
||||
}
|
||||
Review review = new Review();
|
||||
review.setOrderId(orderId);
|
||||
review.setProductId(productId);
|
||||
review.setCustomerId(customerId);
|
||||
review.setRating(rating);
|
||||
review.setContent(content);
|
||||
return reviewRepository.save(review);
|
||||
}
|
||||
|
||||
public Map<String, Object> merchantOverview(Long merchantId) {
|
||||
List<Orders> orders = ordersRepository.findByMerchantId(merchantId);
|
||||
BigDecimal sales = orders.stream()
|
||||
.filter(o -> o.getStatus() == OrderStatus.PAID || o.getStatus() == OrderStatus.SHIPPED || o.getStatus() == OrderStatus.COMPLETED)
|
||||
.map(Orders::getTotalAmount)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
Map<Long, Integer> hotMap = new HashMap<>();
|
||||
Map<String, Long> categoryCount = new HashMap<>();
|
||||
for (Orders order : orders) {
|
||||
for (OrderItem item : orderItemRepository.findByOrderId(order.getId())) {
|
||||
hotMap.put(item.getProductId(), hotMap.getOrDefault(item.getProductId(), 0) + item.getQuantity());
|
||||
}
|
||||
}
|
||||
for (Product p : productRepository.findByMerchantId(merchantId)) {
|
||||
String category = p.getCategory() == null ? "未分类" : p.getCategory();
|
||||
categoryCount.put(category, categoryCount.getOrDefault(category, 0L) + 1);
|
||||
}
|
||||
return Map.of(
|
||||
"orderCount", orders.size(),
|
||||
"salesAmount", sales,
|
||||
"hotProducts", hotMap,
|
||||
"categoryRatio", categoryCount,
|
||||
"notifications", List.of("请及时处理退款申请", "注意库存预警")
|
||||
);
|
||||
}
|
||||
|
||||
public Product merchantSaveProduct(Long merchantId, Product body) {
|
||||
Product product = body;
|
||||
if (product.getId() != null) {
|
||||
Product old = productRepository.findById(product.getId()).orElseThrow(() -> new BizException("商品不存在"));
|
||||
if (!old.getMerchantId().equals(merchantId)) {
|
||||
throw new BizException("无权限操作");
|
||||
}
|
||||
}
|
||||
product.setMerchantId(merchantId);
|
||||
if (product.getApproved() == null) {
|
||||
product.setApproved(false);
|
||||
}
|
||||
Product saved = productRepository.save(product);
|
||||
InventoryRecord record = new InventoryRecord();
|
||||
record.setMerchantId(merchantId);
|
||||
record.setProductId(saved.getId());
|
||||
record.setChangeQty(saved.getStock());
|
||||
record.setNote("商品上架或更新库存");
|
||||
inventoryRecordRepository.save(record);
|
||||
return saved;
|
||||
}
|
||||
|
||||
public List<Product> merchantProducts(Long merchantId) {
|
||||
return productRepository.findByMerchantId(merchantId);
|
||||
}
|
||||
|
||||
public void merchantDeleteProduct(Long merchantId, Long productId) {
|
||||
Product product = getProduct(productId);
|
||||
if (!product.getMerchantId().equals(merchantId)) {
|
||||
throw new BizException("无权限操作");
|
||||
}
|
||||
productRepository.delete(product);
|
||||
}
|
||||
|
||||
public List<Orders> merchantOrders(Long merchantId) {
|
||||
return ordersRepository.findByMerchantId(merchantId);
|
||||
}
|
||||
|
||||
public Orders merchantShip(Long merchantId, Long orderId, String note) {
|
||||
Orders order = ordersRepository.findById(orderId).orElseThrow(() -> new BizException("订单不存在"));
|
||||
if (!order.getMerchantId().equals(merchantId)) {
|
||||
throw new BizException("无权限操作");
|
||||
}
|
||||
order.setStatus(OrderStatus.SHIPPED);
|
||||
order.setLogisticsInfo(note);
|
||||
ordersRepository.save(order);
|
||||
|
||||
LogisticsRecord record = new LogisticsRecord();
|
||||
record.setOrderId(orderId);
|
||||
record.setMerchantId(merchantId);
|
||||
record.setStatus("SHIPPED");
|
||||
record.setNote(note);
|
||||
logisticsRecordRepository.save(record);
|
||||
return order;
|
||||
}
|
||||
|
||||
public Orders merchantProcessRefund(Long merchantId, Long orderId, boolean agree) {
|
||||
Orders order = ordersRepository.findById(orderId).orElseThrow(() -> new BizException("订单不存在"));
|
||||
if (!order.getMerchantId().equals(merchantId)) {
|
||||
throw new BizException("无权限操作");
|
||||
}
|
||||
if (order.getStatus() != OrderStatus.REFUND_REQUESTED) {
|
||||
throw new BizException("仅退款申请中的订单可处理");
|
||||
}
|
||||
order.setStatus(agree ? OrderStatus.REFUNDED : OrderStatus.PAID);
|
||||
return ordersRepository.save(order);
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> merchantReviews(Long merchantId) {
|
||||
List<Product> products = productRepository.findByMerchantId(merchantId);
|
||||
Set<Long> productIds = new HashSet<>();
|
||||
for (Product product : products) {
|
||||
productIds.add(product.getId());
|
||||
}
|
||||
List<Review> reviews = reviewRepository.findAll();
|
||||
Map<Long, Orders> orderMap = new HashMap<>();
|
||||
for (Orders order : ordersRepository.findAll()) {
|
||||
orderMap.put(order.getId(), order);
|
||||
}
|
||||
List<Map<String, Object>> views = new ArrayList<>();
|
||||
for (Review r : reviews) {
|
||||
if (!productIds.contains(r.getProductId())) continue;
|
||||
Orders order = orderMap.get(r.getOrderId());
|
||||
Map<String, Object> row = new HashMap<>();
|
||||
row.put("id", r.getId());
|
||||
row.put("orderId", r.getOrderId());
|
||||
row.put("orderNo", order == null ? "" : order.getOrderNo());
|
||||
row.put("productId", r.getProductId());
|
||||
row.put("productName", products.stream().filter(p -> p.getId().equals(r.getProductId())).findFirst().map(Product::getName).orElse(""));
|
||||
row.put("rating", r.getRating());
|
||||
row.put("content", r.getContent());
|
||||
row.put("createdAt", r.getCreatedAt());
|
||||
views.add(row);
|
||||
}
|
||||
return views;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> merchantLogistics(Long merchantId) {
|
||||
List<LogisticsRecord> records = logisticsRecordRepository.findByMerchantId(merchantId);
|
||||
Map<Long, Orders> orderMap = new HashMap<>();
|
||||
for (Orders order : ordersRepository.findAll()) {
|
||||
orderMap.put(order.getId(), order);
|
||||
}
|
||||
List<Map<String, Object>> views = new ArrayList<>();
|
||||
for (LogisticsRecord rec : records) {
|
||||
Orders order = orderMap.get(rec.getOrderId());
|
||||
Map<String, Object> row = new HashMap<>();
|
||||
row.put("id", rec.getId());
|
||||
row.put("orderId", rec.getOrderId());
|
||||
row.put("orderNo", order == null ? "" : order.getOrderNo());
|
||||
row.put("status", rec.getStatus());
|
||||
row.put("note", rec.getNote());
|
||||
row.put("createdAt", rec.getCreatedAt());
|
||||
views.add(row);
|
||||
}
|
||||
return views;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> merchantInventory(Long merchantId) {
|
||||
List<InventoryRecord> records = inventoryRecordRepository.findByMerchantId(merchantId);
|
||||
Map<Long, Product> productMap = new HashMap<>();
|
||||
for (Product product : productRepository.findByMerchantId(merchantId)) {
|
||||
productMap.put(product.getId(), product);
|
||||
}
|
||||
List<Map<String, Object>> views = new ArrayList<>();
|
||||
for (InventoryRecord rec : records) {
|
||||
Product product = productMap.get(rec.getProductId());
|
||||
Map<String, Object> row = new HashMap<>();
|
||||
row.put("id", rec.getId());
|
||||
row.put("productId", rec.getProductId());
|
||||
row.put("productName", product == null ? "" : product.getName());
|
||||
row.put("changeQty", rec.getChangeQty());
|
||||
row.put("note", rec.getNote());
|
||||
row.put("createdAt", rec.getCreatedAt());
|
||||
views.add(row);
|
||||
}
|
||||
return views;
|
||||
}
|
||||
|
||||
public void merchantDeleteInventory(Long merchantId, Long id) {
|
||||
InventoryRecord rec = inventoryRecordRepository.findById(id).orElseThrow(() -> new BizException("记录不存在"));
|
||||
if (!rec.getMerchantId().equals(merchantId)) {
|
||||
throw new BizException("无权限操作");
|
||||
}
|
||||
inventoryRecordRepository.delete(rec);
|
||||
}
|
||||
|
||||
public MerchantApplication applyMerchant(Long userId, String qualification) {
|
||||
User user = userRepository.findById(userId).orElseThrow(() -> new BizException("用户不存在"));
|
||||
if (user.getRole() != UserRole.CUSTOMER) {
|
||||
throw new BizException("仅顾客账号可提交入驻申请");
|
||||
}
|
||||
if (merchantApplicationRepository.existsByUserIdAndStatus(userId, "PENDING")) {
|
||||
throw new BizException("已有待审核申请,请勿重复提交");
|
||||
}
|
||||
MerchantApplication m = new MerchantApplication();
|
||||
m.setUserId(userId);
|
||||
m.setQualification(qualification);
|
||||
m.setStatus("PENDING");
|
||||
return merchantApplicationRepository.save(m);
|
||||
}
|
||||
|
||||
public Map<String, Object> adminOverview() {
|
||||
List<Orders> orders = ordersRepository.findAll();
|
||||
BigDecimal sales = orders.stream().map(Orders::getTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
Map<String, Long> categoryCount = new HashMap<>();
|
||||
Map<Long, Integer> hotMap = new HashMap<>();
|
||||
for (Product p : productRepository.findAll()) {
|
||||
String category = p.getCategory() == null ? "未分类" : p.getCategory();
|
||||
categoryCount.put(category, categoryCount.getOrDefault(category, 0L) + 1);
|
||||
}
|
||||
for (Orders order : orders) {
|
||||
for (OrderItem item : orderItemRepository.findByOrderId(order.getId())) {
|
||||
hotMap.put(item.getProductId(), hotMap.getOrDefault(item.getProductId(), 0) + item.getQuantity());
|
||||
}
|
||||
}
|
||||
return Map.of(
|
||||
"orderCount", orders.size(),
|
||||
"salesAmount", sales,
|
||||
"categoryRatio", categoryCount,
|
||||
"hotProducts", hotMap
|
||||
);
|
||||
}
|
||||
|
||||
public List<Orders> adminOrders() {
|
||||
return ordersRepository.findAll();
|
||||
}
|
||||
|
||||
public Orders adminUpdateOrder(Long orderId, String status, String logisticsInfo) {
|
||||
Orders order = ordersRepository.findById(orderId).orElseThrow(() -> new BizException("订单不存在"));
|
||||
try {
|
||||
order.setStatus(OrderStatus.valueOf(status));
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new BizException("订单状态不合法");
|
||||
}
|
||||
order.setLogisticsInfo(logisticsInfo);
|
||||
return ordersRepository.save(order);
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> adminRiskOrders() {
|
||||
List<Orders> orders = ordersRepository.findAll();
|
||||
List<Map<String, Object>> risks = new ArrayList<>();
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
for (Orders order : orders) {
|
||||
if (order.getTotalAmount().compareTo(new BigDecimal("5000")) >= 0) {
|
||||
risks.add(buildRisk(order, "HIGH_AMOUNT", "订单金额较高,请人工核查"));
|
||||
}
|
||||
if (order.getStatus() == OrderStatus.PAID && order.getCreatedAt() != null && order.getCreatedAt().isBefore(now.minusDays(2))) {
|
||||
risks.add(buildRisk(order, "SHIP_DELAY", "已支付超过48小时未发货"));
|
||||
}
|
||||
if (order.getStatus() == OrderStatus.SHIPPED && logisticsRecordRepository.findByOrderId(order.getId()).isEmpty()) {
|
||||
risks.add(buildRisk(order, "NO_LOGISTICS", "订单标记已发货但无物流轨迹"));
|
||||
}
|
||||
if (order.getStatus() == OrderStatus.REFUND_REQUESTED) {
|
||||
risks.add(buildRisk(order, "REFUND_PENDING", "退款申请待审核"));
|
||||
}
|
||||
}
|
||||
return risks;
|
||||
}
|
||||
|
||||
private Map<String, Object> buildRisk(Orders order, String type, String reason) {
|
||||
Map<String, Object> row = new HashMap<>();
|
||||
row.put("orderId", order.getId());
|
||||
row.put("orderNo", order.getOrderNo());
|
||||
row.put("status", order.getStatus());
|
||||
row.put("totalAmount", order.getTotalAmount());
|
||||
row.put("customerId", order.getCustomerId());
|
||||
row.put("merchantId", order.getMerchantId());
|
||||
row.put("riskType", type);
|
||||
row.put("riskReason", reason);
|
||||
return row;
|
||||
}
|
||||
|
||||
public Orders adminAuditRefund(Long orderId, boolean approve, String remark) {
|
||||
Orders order = ordersRepository.findById(orderId).orElseThrow(() -> new BizException("订单不存在"));
|
||||
if (order.getStatus() != OrderStatus.REFUND_REQUESTED) {
|
||||
throw new BizException("当前订单不在退款审核状态");
|
||||
}
|
||||
order.setStatus(approve ? OrderStatus.REFUNDED : OrderStatus.PAID);
|
||||
if (remark != null && !remark.trim().isEmpty()) {
|
||||
String old = order.getRefundReason() == null ? "" : order.getRefundReason();
|
||||
String merged = old.isBlank() ? remark.trim() : old + ";管理员备注:" + remark.trim();
|
||||
order.setRefundReason(merged);
|
||||
}
|
||||
Orders saved = ordersRepository.save(order);
|
||||
|
||||
LogisticsRecord record = new LogisticsRecord();
|
||||
record.setOrderId(orderId);
|
||||
record.setMerchantId(order.getMerchantId());
|
||||
record.setStatus(approve ? "REFUND_APPROVED" : "REFUND_REJECTED");
|
||||
record.setNote((approve ? "管理员通过退款审核" : "管理员驳回退款申请") + (remark == null || remark.trim().isEmpty() ? "" : (":" + remark.trim())));
|
||||
logisticsRecordRepository.save(record);
|
||||
return saved;
|
||||
}
|
||||
|
||||
public Orders adminAuditShipment(Long orderId, boolean approved, String remark) {
|
||||
Orders order = ordersRepository.findById(orderId).orElseThrow(() -> new BizException("订单不存在"));
|
||||
if (order.getStatus() != OrderStatus.SHIPPED && order.getStatus() != OrderStatus.PAID) {
|
||||
throw new BizException("仅已支付或已发货订单可审核发货");
|
||||
}
|
||||
if (approved && order.getStatus() == OrderStatus.PAID) {
|
||||
order.setStatus(OrderStatus.SHIPPED);
|
||||
}
|
||||
if (!approved && order.getStatus() == OrderStatus.SHIPPED) {
|
||||
order.setStatus(OrderStatus.PAID);
|
||||
}
|
||||
if (remark != null && !remark.trim().isEmpty()) {
|
||||
order.setLogisticsInfo(remark.trim());
|
||||
}
|
||||
Orders saved = ordersRepository.save(order);
|
||||
|
||||
LogisticsRecord record = new LogisticsRecord();
|
||||
record.setOrderId(orderId);
|
||||
record.setMerchantId(order.getMerchantId());
|
||||
record.setStatus(approved ? "SHIP_AUDIT_PASS" : "SHIP_AUDIT_REJECT");
|
||||
record.setNote((approved ? "管理员发货审核通过" : "管理员发货审核驳回") + (remark == null || remark.trim().isEmpty() ? "" : (":" + remark.trim())));
|
||||
logisticsRecordRepository.save(record);
|
||||
return saved;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> adminMerchantApplications() {
|
||||
List<MerchantApplication> apps = merchantApplicationRepository.findAll();
|
||||
List<Map<String, Object>> views = new ArrayList<>();
|
||||
Map<Long, User> userMap = new HashMap<>();
|
||||
for (User user : userRepository.findAll()) {
|
||||
userMap.put(user.getId(), user);
|
||||
}
|
||||
for (MerchantApplication app : apps) {
|
||||
User applicant = userMap.get(app.getUserId());
|
||||
Map<String, Object> row = new HashMap<>();
|
||||
row.put("id", app.getId());
|
||||
row.put("userId", app.getUserId());
|
||||
row.put("applicantUsername", applicant == null ? "" : applicant.getUsername());
|
||||
row.put("applicantNickname", applicant == null ? "" : applicant.getNickname());
|
||||
row.put("qualification", app.getQualification());
|
||||
row.put("status", app.getStatus());
|
||||
row.put("remark", app.getRemark());
|
||||
views.add(row);
|
||||
}
|
||||
return views;
|
||||
}
|
||||
|
||||
public MerchantApplication adminAuditApplication(Long id, String status, String remark) {
|
||||
MerchantApplication app = merchantApplicationRepository.findById(id).orElseThrow(() -> new BizException("申请不存在"));
|
||||
app.setStatus(status);
|
||||
app.setRemark(remark);
|
||||
merchantApplicationRepository.save(app);
|
||||
|
||||
if ("APPROVED".equals(status)) {
|
||||
User user = userRepository.findById(app.getUserId()).orElseThrow(() -> new BizException("用户不存在"));
|
||||
user.setRole(UserRole.MERCHANT);
|
||||
userRepository.save(user);
|
||||
}
|
||||
return app;
|
||||
}
|
||||
|
||||
public List<User> adminUsers() {
|
||||
return userRepository.findAll();
|
||||
}
|
||||
|
||||
public User adminSaveUser(User user) {
|
||||
String username = user.getUsername() == null ? "" : user.getUsername().trim();
|
||||
String password = user.getPassword() == null ? "" : user.getPassword().trim();
|
||||
if (username.isEmpty()) {
|
||||
throw new BizException("用户名不能为空");
|
||||
}
|
||||
if (password.isEmpty()) {
|
||||
throw new BizException("密码不能为空");
|
||||
}
|
||||
|
||||
if (user.getId() == null) {
|
||||
userRepository.findByUsername(username).ifPresent(u -> {
|
||||
throw new BizException("账号已存在");
|
||||
});
|
||||
} else {
|
||||
User existing = userRepository.findById(user.getId()).orElseThrow(() -> new BizException("用户不存在"));
|
||||
userRepository.findByUsername(username).ifPresent(u -> {
|
||||
if (!u.getId().equals(existing.getId())) {
|
||||
throw new BizException("账号已存在");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
user.setUsername(username);
|
||||
user.setPassword(password);
|
||||
if (user.getRole() == null) {
|
||||
user.setRole(UserRole.CUSTOMER);
|
||||
}
|
||||
if (user.getNickname() == null || user.getNickname().trim().isEmpty()) {
|
||||
user.setNickname(username);
|
||||
}
|
||||
if (user.getEnabled() == null) {
|
||||
user.setEnabled(true);
|
||||
}
|
||||
return userRepository.save(user);
|
||||
}
|
||||
|
||||
public void adminDeleteUser(Long id) {
|
||||
userRepository.deleteById(id);
|
||||
}
|
||||
|
||||
public List<Banner> adminBanners() {
|
||||
return bannerRepository.findAll();
|
||||
}
|
||||
|
||||
public Banner adminSaveBanner(Banner banner) {
|
||||
return bannerRepository.save(banner);
|
||||
}
|
||||
|
||||
public void adminDeleteBanner(Long id) {
|
||||
bannerRepository.deleteById(id);
|
||||
}
|
||||
|
||||
public List<Product> adminProducts() {
|
||||
return productRepository.findAll();
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> adminProductViews() {
|
||||
List<Product> products = productRepository.findAll();
|
||||
Map<Long, User> userMap = new HashMap<>();
|
||||
for (User user : userRepository.findAll()) {
|
||||
userMap.put(user.getId(), user);
|
||||
}
|
||||
List<Map<String, Object>> views = new ArrayList<>();
|
||||
for (Product p : products) {
|
||||
User merchant = userMap.get(p.getMerchantId());
|
||||
Map<String, Object> row = new HashMap<>();
|
||||
row.put("id", p.getId());
|
||||
row.put("name", p.getName());
|
||||
row.put("category", p.getCategory());
|
||||
row.put("description", p.getDescription());
|
||||
row.put("price", p.getPrice());
|
||||
row.put("stock", p.getStock());
|
||||
row.put("imageUrl", p.getImageUrl());
|
||||
row.put("merchantId", p.getMerchantId());
|
||||
row.put("merchantUsername", merchant == null ? "" : merchant.getUsername());
|
||||
row.put("merchantName", merchant == null ? "" : merchant.getNickname());
|
||||
row.put("approved", p.getApproved());
|
||||
row.put("createdAt", p.getCreatedAt());
|
||||
views.add(row);
|
||||
}
|
||||
return views;
|
||||
}
|
||||
|
||||
public Product adminSaveProduct(Product input) {
|
||||
if (input.getName() == null || input.getName().trim().isEmpty()) {
|
||||
throw new BizException("商品名称不能为空");
|
||||
}
|
||||
if (input.getMerchantId() == null) {
|
||||
throw new BizException("商家ID不能为空");
|
||||
}
|
||||
if (input.getPrice() == null || input.getStock() == null) {
|
||||
throw new BizException("商品价格或库存不能为空");
|
||||
}
|
||||
Product product = input;
|
||||
if (input.getId() != null) {
|
||||
product = productRepository.findById(input.getId()).orElseThrow(() -> new BizException("商品不存在"));
|
||||
product.setName(input.getName());
|
||||
product.setCategory(input.getCategory());
|
||||
product.setDescription(input.getDescription());
|
||||
product.setPrice(input.getPrice());
|
||||
product.setStock(input.getStock());
|
||||
product.setImageUrl(input.getImageUrl());
|
||||
product.setMerchantId(input.getMerchantId());
|
||||
product.setApproved(Boolean.TRUE.equals(input.getApproved()));
|
||||
} else {
|
||||
if (product.getApproved() == null) {
|
||||
product.setApproved(false);
|
||||
}
|
||||
}
|
||||
return productRepository.save(product);
|
||||
}
|
||||
|
||||
public Product adminApproveProduct(Long productId, boolean approved) {
|
||||
Product product = productRepository.findById(productId).orElseThrow(() -> new BizException("商品不存在"));
|
||||
product.setApproved(approved);
|
||||
return productRepository.save(product);
|
||||
}
|
||||
|
||||
public void adminDeleteProduct(Long id) {
|
||||
productRepository.deleteById(id);
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> adminReviews() {
|
||||
List<Review> reviews = reviewRepository.findAll();
|
||||
Map<Long, User> userMap = new HashMap<>();
|
||||
for (User user : userRepository.findAll()) {
|
||||
userMap.put(user.getId(), user);
|
||||
}
|
||||
Map<Long, Orders> orderMap = new HashMap<>();
|
||||
for (Orders order : ordersRepository.findAll()) {
|
||||
orderMap.put(order.getId(), order);
|
||||
}
|
||||
Map<Long, Product> productMap = new HashMap<>();
|
||||
for (Product product : productRepository.findAll()) {
|
||||
productMap.put(product.getId(), product);
|
||||
}
|
||||
List<Map<String, Object>> views = new ArrayList<>();
|
||||
for (Review r : reviews) {
|
||||
User customer = userMap.get(r.getCustomerId());
|
||||
Orders order = orderMap.get(r.getOrderId());
|
||||
Product product = productMap.get(r.getProductId());
|
||||
Map<String, Object> row = new HashMap<>();
|
||||
row.put("id", r.getId());
|
||||
row.put("orderId", r.getOrderId());
|
||||
row.put("orderNo", order == null ? "" : order.getOrderNo());
|
||||
row.put("productId", r.getProductId());
|
||||
row.put("productName", product == null ? "" : product.getName());
|
||||
row.put("customerId", r.getCustomerId());
|
||||
row.put("customerUsername", customer == null ? "" : customer.getUsername());
|
||||
row.put("rating", r.getRating());
|
||||
row.put("content", r.getContent());
|
||||
row.put("createdAt", r.getCreatedAt());
|
||||
views.add(row);
|
||||
}
|
||||
return views;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> adminLogistics() {
|
||||
List<LogisticsRecord> records = logisticsRecordRepository.findAll();
|
||||
Map<Long, User> userMap = new HashMap<>();
|
||||
for (User user : userRepository.findAll()) {
|
||||
userMap.put(user.getId(), user);
|
||||
}
|
||||
Map<Long, Orders> orderMap = new HashMap<>();
|
||||
for (Orders order : ordersRepository.findAll()) {
|
||||
orderMap.put(order.getId(), order);
|
||||
}
|
||||
List<Map<String, Object>> views = new ArrayList<>();
|
||||
for (LogisticsRecord rec : records) {
|
||||
User merchant = userMap.get(rec.getMerchantId());
|
||||
Orders order = orderMap.get(rec.getOrderId());
|
||||
Map<String, Object> row = new HashMap<>();
|
||||
row.put("id", rec.getId());
|
||||
row.put("orderId", rec.getOrderId());
|
||||
row.put("orderNo", order == null ? "" : order.getOrderNo());
|
||||
row.put("merchantId", rec.getMerchantId());
|
||||
row.put("merchantUsername", merchant == null ? "" : merchant.getUsername());
|
||||
row.put("status", rec.getStatus());
|
||||
row.put("note", rec.getNote());
|
||||
row.put("createdAt", rec.getCreatedAt());
|
||||
views.add(row);
|
||||
}
|
||||
return views;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> adminInventory() {
|
||||
List<InventoryRecord> records = inventoryRecordRepository.findAll();
|
||||
Map<Long, User> userMap = new HashMap<>();
|
||||
for (User user : userRepository.findAll()) {
|
||||
userMap.put(user.getId(), user);
|
||||
}
|
||||
Map<Long, Product> productMap = new HashMap<>();
|
||||
for (Product product : productRepository.findAll()) {
|
||||
productMap.put(product.getId(), product);
|
||||
}
|
||||
List<Map<String, Object>> views = new ArrayList<>();
|
||||
for (InventoryRecord rec : records) {
|
||||
User merchant = userMap.get(rec.getMerchantId());
|
||||
Product product = productMap.get(rec.getProductId());
|
||||
Map<String, Object> row = new HashMap<>();
|
||||
row.put("id", rec.getId());
|
||||
row.put("productId", rec.getProductId());
|
||||
row.put("productName", product == null ? "" : product.getName());
|
||||
row.put("merchantId", rec.getMerchantId());
|
||||
row.put("merchantUsername", merchant == null ? "" : merchant.getUsername());
|
||||
row.put("changeQty", rec.getChangeQty());
|
||||
row.put("note", rec.getNote());
|
||||
row.put("createdAt", rec.getCreatedAt());
|
||||
views.add(row);
|
||||
}
|
||||
return views;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user