完善代码
This commit is contained in:
@@ -57,8 +57,9 @@ export const orderApi = {
|
||||
}))
|
||||
},
|
||||
|
||||
getList(params?: PageParams & { status?: string }): Promise<ApiResponse<PageResponse<Order>>> {
|
||||
getList(params?: PageParams & { status?: string; userId?: number }): Promise<ApiResponse<PageResponse<Order>>> {
|
||||
return request.post<ApiResponse<Record<string, any>>>('/api/order/my-orders', {
|
||||
userId: params?.userId,
|
||||
status: orderStatusToCode(params?.status),
|
||||
page: params?.page ?? 0,
|
||||
size: params?.size ?? 10,
|
||||
@@ -122,7 +123,7 @@ export const orderApi = {
|
||||
return request.delete(`/api/order/${id}`)
|
||||
},
|
||||
|
||||
getStatistics(): Promise<ApiResponse<{
|
||||
getStatistics(userId?: number): Promise<ApiResponse<{
|
||||
total: number;
|
||||
pending: number;
|
||||
paid: number;
|
||||
@@ -130,7 +131,7 @@ export const orderApi = {
|
||||
completed: number;
|
||||
cancelled: number
|
||||
}>> {
|
||||
return request.get<ApiResponse<any>>('/api/order/statistics').then((res) => ({
|
||||
return request.get<ApiResponse<any>>('/api/order/statistics', userId ? {userId} : undefined).then((res) => ({
|
||||
...res,
|
||||
data: {
|
||||
total: Number(res.data.totalOrders || 0),
|
||||
|
||||
@@ -58,22 +58,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 热门搜索 -->
|
||||
<div v-if="!searchQuery" class="search-section">
|
||||
<div class="section-header">
|
||||
<span class="title">热门搜索</span>
|
||||
</div>
|
||||
<div class="tag-list">
|
||||
<el-tag
|
||||
v-for="item in hotSearches"
|
||||
:key="item"
|
||||
@click="selectHot(item)"
|
||||
>
|
||||
{{ item }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 搜索建议 -->
|
||||
<div v-if="searchQuery && suggestions.length > 0" class="search-suggestions">
|
||||
<div class="section-header">
|
||||
@@ -116,7 +100,7 @@
|
||||
<el-select v-model="advancedForm.category" placeholder="选择分类">
|
||||
<el-option label="全部分类" value=""/>
|
||||
<el-option v-for="item in categories" :key="item" :label="item" :value="item"/>
|
||||
<el-option label="图书音像" value="books"/>
|
||||
<!-- <el-option label="图书音像" value="books"/>-->
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="价格区间">
|
||||
@@ -157,7 +141,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {ref, reactive, watch, onMounted} from 'vue'
|
||||
import {onMounted, reactive, ref, watch} from 'vue'
|
||||
import {useRouter} from 'vue-router'
|
||||
import {debounce} from 'lodash-es'
|
||||
import {productApi} from '@/api/modules/product'
|
||||
@@ -172,16 +156,6 @@ const activeCollapse = ref<string[]>([])
|
||||
// 搜索历史
|
||||
const searchHistory = ref<string[]>([])
|
||||
|
||||
// 热门搜索
|
||||
const hotSearches = ref([
|
||||
'iPhone 15',
|
||||
'MacBook Pro',
|
||||
'限时活动',
|
||||
'AirPods',
|
||||
'限时特价',
|
||||
'新品上市'
|
||||
])
|
||||
|
||||
// 搜索建议
|
||||
const suggestions = ref<any[]>([])
|
||||
const categories = ref<string[]>([])
|
||||
|
||||
@@ -95,7 +95,8 @@
|
||||
<template #default="{ row }">
|
||||
<el-button text type="primary" @click="openDetail(row.id)">查看</el-button>
|
||||
<el-button text type="primary" @click="openEditDialog(row.id)">编辑</el-button>
|
||||
<el-button text type="danger" @click="removeProduct(row)">删除</el-button>
|
||||
<el-button v-if="row.status === 1" text type="danger" @click="removeProduct(row)">下架</el-button>
|
||||
<el-button v-else disabled text type="info">已下架</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -185,8 +186,8 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {onMounted, reactive, ref} from 'vue'
|
||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||
import type {FormInstance, FormRules} from 'element-plus'
|
||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||
import dayjs from 'dayjs'
|
||||
import ImageUpload from '@/components/common/ImageUpload.vue'
|
||||
import SafeImage from '@/components/common/SafeImage.vue'
|
||||
@@ -207,7 +208,7 @@ const categories = ref<string[]>([])
|
||||
const query = reactive({
|
||||
keyword: '',
|
||||
category: '',
|
||||
status: '' as number | '',
|
||||
status: 1 as number | '',
|
||||
})
|
||||
|
||||
const pagination = reactive({
|
||||
@@ -348,12 +349,19 @@ const submitForm = async () => {
|
||||
}
|
||||
|
||||
const removeProduct = async (row: AdminProductRow) => {
|
||||
await ElMessageBox.confirm(`确定删除商品“${row.name}”吗?`, '删除确认', {
|
||||
type: 'warning',
|
||||
})
|
||||
await adminApi.deleteProduct(row.id)
|
||||
ElMessage.success('商品已删除')
|
||||
await reloadData()
|
||||
try {
|
||||
await ElMessageBox.confirm(`确定下架商品“${row.name}”吗?下架后前台将不再展示该商品,历史订单仍会保留。`, '下架确认', {
|
||||
type: 'warning',
|
||||
confirmButtonText: '确认下架',
|
||||
cancelButtonText: '取消',
|
||||
})
|
||||
await adminApi.deleteProduct(row.id)
|
||||
ElMessage.success('商品已下架')
|
||||
await reloadData()
|
||||
} catch (error: any) {
|
||||
if (error === 'cancel' || error === 'close') return
|
||||
ElMessage.error(error?.message || '商品下架失败')
|
||||
}
|
||||
}
|
||||
|
||||
const handleSearch = () => {
|
||||
@@ -364,7 +372,7 @@ const handleSearch = () => {
|
||||
const handleReset = () => {
|
||||
query.keyword = ''
|
||||
query.category = ''
|
||||
query.status = ''
|
||||
query.status = 1
|
||||
handleSearch()
|
||||
}
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {ref, onMounted} from 'vue'
|
||||
import {onMounted, ref} from 'vue'
|
||||
import {useRouter} from 'vue-router'
|
||||
import {ElMessage} from 'element-plus'
|
||||
import FlashSaleCard from '@/components/business/FlashSaleCard.vue'
|
||||
@@ -239,7 +239,7 @@ const categoryIconMap: Record<string, string> = {
|
||||
'电子产品': 'Monitor',
|
||||
'家电': 'House',
|
||||
'服饰鞋包': 'Goods',
|
||||
'图书音像': 'Reading',
|
||||
// '图书音像': 'Reading',
|
||||
'食品饮料': 'Coffee',
|
||||
'运动户外': 'Trophy',
|
||||
'美妆护肤': 'MagicStick',
|
||||
|
||||
@@ -156,12 +156,13 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {ref, reactive, onMounted} from 'vue'
|
||||
import {onMounted, reactive, ref} from 'vue'
|
||||
import {useRouter} from 'vue-router'
|
||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||
import {orderApi} from '@/api/modules/order'
|
||||
import {reviewApi} from '@/api/modules/review'
|
||||
import {useCartStore} from '@/stores/cart'
|
||||
import {useUserStore} from '@/stores/user'
|
||||
import type {Order} from '@/types/api'
|
||||
import dayjs from 'dayjs'
|
||||
import SafeImage from '@/components/common/SafeImage.vue'
|
||||
@@ -170,6 +171,7 @@ import ReturnDialog from '@/components/business/ReturnDialog.vue'
|
||||
|
||||
const router = useRouter()
|
||||
const cartStore = useCartStore()
|
||||
const userStore = useUserStore()
|
||||
|
||||
const loading = ref(false)
|
||||
const orders = ref<Order[]>([])
|
||||
@@ -213,9 +215,17 @@ const getStatusText = (status: string) => ({
|
||||
}[status] || status)
|
||||
|
||||
const loadOrders = async () => {
|
||||
const currentUserId = userStore.user?.id
|
||||
if (!currentUserId) {
|
||||
ElMessage.warning('请先登录后查看订单')
|
||||
await router.push({path: '/login', query: {redirect: '/orders'}})
|
||||
return
|
||||
}
|
||||
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await orderApi.getList({
|
||||
userId: currentUserId,
|
||||
page: pagination.page - 1,
|
||||
size: pagination.size,
|
||||
status: filters.status || undefined
|
||||
@@ -236,7 +246,10 @@ const loadOrders = async () => {
|
||||
|
||||
const loadStatistics = async () => {
|
||||
try {
|
||||
const res = await orderApi.getStatistics()
|
||||
const currentUserId = userStore.user?.id
|
||||
if (!currentUserId) return
|
||||
|
||||
const res = await orderApi.getStatistics(currentUserId)
|
||||
if (res.success) {
|
||||
orderStats.value[0].count = res.data.total
|
||||
orderStats.value[1].count = res.data.pending
|
||||
|
||||
@@ -445,7 +445,7 @@ public class AdminController {
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", true);
|
||||
response.put("message", "商品删除成功");
|
||||
response.put("message", "商品已下架");
|
||||
|
||||
return ResponseEntity.ok(response);
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.org.flashsalesystem.controller;
|
||||
|
||||
import com.org.flashsalesystem.dto.FlashSaleDTO;
|
||||
import com.org.flashsalesystem.dto.ProductDTO;
|
||||
import com.org.flashsalesystem.entity.Product;
|
||||
import com.org.flashsalesystem.repository.ProductRepository;
|
||||
import com.org.flashsalesystem.service.FlashSaleService;
|
||||
@@ -18,7 +17,10 @@ import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* API控制器 - 为Vue前端提供REST接口
|
||||
@@ -47,7 +49,7 @@ public class ApiController {
|
||||
try {
|
||||
// 获取前N个商品作为热门商品
|
||||
Pageable pageable = PageRequest.of(0, limit, Sort.by(Sort.Direction.DESC, "id"));
|
||||
Page<Product> productPage = productRepository.findAll(pageable);
|
||||
Page<Product> productPage = productRepository.findByStatus(1, pageable);
|
||||
|
||||
List<Map<String, Object>> products = new ArrayList<>();
|
||||
for (Product product : productPage.getContent()) {
|
||||
@@ -175,7 +177,7 @@ public class ApiController {
|
||||
|
||||
try {
|
||||
Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "id"));
|
||||
Page<Product> productPage = productRepository.findAll(pageable);
|
||||
Page<Product> productPage = productRepository.findByStatus(1, pageable);
|
||||
|
||||
List<Map<String, Object>> products = new ArrayList<>();
|
||||
for (Product product : productPage.getContent()) {
|
||||
|
||||
@@ -288,9 +288,23 @@ public class OrderController {
|
||||
* 获取订单统计信息
|
||||
*/
|
||||
@GetMapping("/statistics")
|
||||
public ResponseEntity<Map<String, Object>> getOrderStatistics() {
|
||||
public ResponseEntity<Map<String, Object>> getOrderStatistics(@RequestParam(required = false) Long userId,
|
||||
HttpServletRequest request) {
|
||||
try {
|
||||
OrderDTO.StatisticsDTO statistics = orderService.getOrderStatistics();
|
||||
UserDTO currentUser = getCurrentUser(request);
|
||||
if (currentUser == null) {
|
||||
return createUnauthorizedResponse();
|
||||
}
|
||||
|
||||
if (userId != null && !userId.equals(currentUser.getId()) && !"ADMIN".equalsIgnoreCase(currentUser.getRole())) {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", false);
|
||||
response.put("message", "无权限查看此用户订单统计");
|
||||
return ResponseEntity.status(403).body(response);
|
||||
}
|
||||
|
||||
Long targetUserId = userId != null ? userId : currentUser.getId();
|
||||
OrderDTO.StatisticsDTO statistics = orderService.getUserOrderStatistics(targetUserId);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", true);
|
||||
@@ -528,15 +542,27 @@ public class OrderController {
|
||||
}
|
||||
|
||||
private UserDTO getCurrentUser(HttpServletRequest request) {
|
||||
String token = null;
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session == null) {
|
||||
return null;
|
||||
if (session != null) {
|
||||
token = (String) session.getAttribute("token");
|
||||
}
|
||||
|
||||
if (token == null || token.trim().isEmpty()) {
|
||||
token = resolveBearerToken(request);
|
||||
}
|
||||
|
||||
String token = (String) session.getAttribute("token");
|
||||
return userService.getUserByToken(token);
|
||||
}
|
||||
|
||||
private String resolveBearerToken(HttpServletRequest request) {
|
||||
String authorization = request.getHeader("Authorization");
|
||||
if (authorization == null || !authorization.startsWith("Bearer ")) {
|
||||
return null;
|
||||
}
|
||||
return authorization.substring("Bearer ".length()).trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户ID
|
||||
*/
|
||||
|
||||
@@ -244,7 +244,7 @@ public class ProductController {
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", success);
|
||||
response.put("message", success ? "商品删除成功" : "商品删除失败");
|
||||
response.put("message", success ? "商品已下架" : "商品下架失败");
|
||||
|
||||
return ResponseEntity.ok(response);
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -788,14 +788,12 @@ public class AdminService {
|
||||
try {
|
||||
Optional<Product> productOpt = productRepository.findById(id);
|
||||
if (productOpt.isPresent()) {
|
||||
Product product = productOpt.get();
|
||||
// 清理磁盘上的图片文件
|
||||
fileUploadService.deleteProductImage(product.getImageUrl());
|
||||
productService.invalidateProductCaches(id);
|
||||
productService.removeProductStockCache(id);
|
||||
// 清除关联的限时活动缓存
|
||||
invalidateFlashSaleCacheByProductId(id);
|
||||
productRepository.deleteById(id);
|
||||
boolean deleted = productService.deleteProduct(id);
|
||||
if (!deleted) {
|
||||
throw new RuntimeException("商品删除失败");
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("商品不存在");
|
||||
}
|
||||
|
||||
@@ -7,11 +7,7 @@ import com.org.flashsalesystem.entity.GroupBuyingGroup;
|
||||
import com.org.flashsalesystem.entity.Order;
|
||||
import com.org.flashsalesystem.entity.OrderItem;
|
||||
import com.org.flashsalesystem.entity.UserAddress;
|
||||
import com.org.flashsalesystem.repository.GroupBuyingGroupRepository;
|
||||
import com.org.flashsalesystem.repository.OrderItemRepository;
|
||||
import com.org.flashsalesystem.repository.OrderRepository;
|
||||
import com.org.flashsalesystem.repository.ProductRepository;
|
||||
import com.org.flashsalesystem.repository.UserAddressRepository;
|
||||
import com.org.flashsalesystem.repository.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -588,6 +584,61 @@ public class OrderService {
|
||||
return statistics;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户订单统计信息
|
||||
*/
|
||||
public OrderDTO.StatisticsDTO getUserOrderStatistics(Long userId) {
|
||||
if (userId == null) {
|
||||
throw new RuntimeException("用户ID不能为空");
|
||||
}
|
||||
|
||||
List<Order> userOrders = orderRepository.findByUserId(userId);
|
||||
OrderDTO.StatisticsDTO statistics = new OrderDTO.StatisticsDTO();
|
||||
|
||||
statistics.setTotalOrders((long) userOrders.size());
|
||||
statistics.setPendingPaymentOrders(countOrdersByStatus(userOrders, 1));
|
||||
statistics.setPaidOrders(countOrdersByStatus(userOrders, 2));
|
||||
statistics.setShippedOrders(countOrdersByStatus(userOrders, 3));
|
||||
statistics.setCompletedOrders(countOrdersByStatus(userOrders, 4));
|
||||
statistics.setCancelledOrders(countOrdersByStatus(userOrders, 5));
|
||||
statistics.setRefundingOrders(countOrdersByStatus(userOrders, 6));
|
||||
statistics.setRefundedOrders(countOrdersByStatus(userOrders, 7));
|
||||
|
||||
statistics.setNormalOrders(countOrdersByType(userOrders, 1));
|
||||
statistics.setFlashSaleOrders(countOrdersByType(userOrders, 2));
|
||||
statistics.setGroupBuyingOrders(countOrdersByType(userOrders, 3));
|
||||
|
||||
BigDecimal totalAmount = userOrders.stream()
|
||||
.map(Order::getTotalPrice)
|
||||
.filter(Objects::nonNull)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
statistics.setTotalAmount(totalAmount);
|
||||
|
||||
LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
|
||||
LocalDateTime todayEnd = LocalDateTime.now().withHour(23).withMinute(59).withSecond(59);
|
||||
BigDecimal todayAmount = userOrders.stream()
|
||||
.filter(order -> order.getCreatedAt() != null)
|
||||
.filter(order -> !order.getCreatedAt().isBefore(todayStart) && !order.getCreatedAt().isAfter(todayEnd))
|
||||
.map(Order::getTotalPrice)
|
||||
.filter(Objects::nonNull)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
statistics.setTodayAmount(todayAmount);
|
||||
|
||||
return statistics;
|
||||
}
|
||||
|
||||
private Long countOrdersByStatus(List<Order> orders, Integer status) {
|
||||
return orders.stream()
|
||||
.filter(order -> Objects.equals(order.getStatus(), status))
|
||||
.count();
|
||||
}
|
||||
|
||||
private Long countOrdersByType(List<Order> orders, Integer orderType) {
|
||||
return orders.stream()
|
||||
.filter(order -> Objects.equals(order.getOrderType(), orderType))
|
||||
.count();
|
||||
}
|
||||
|
||||
private void createOrderItem(Order order, ProductDTO product, Integer quantity) {
|
||||
OrderItem orderItem = new OrderItem();
|
||||
orderItem.setOrderId(order.getId());
|
||||
|
||||
@@ -31,6 +31,7 @@ public class ProductService {
|
||||
private static final String PRODUCT_STOCK_PREFIX = "product_stock:";
|
||||
private static final String PRODUCT_SALES_RANK = "product_sales_rank";
|
||||
private static final String HOT_PRODUCTS_CACHE = "hot_products";
|
||||
private static final String ACTIVE_FLASH_SALES_CACHE = "active_flashsales";
|
||||
@Autowired
|
||||
private ProductRepository productRepository;
|
||||
@Autowired
|
||||
@@ -474,7 +475,7 @@ public class ProductService {
|
||||
*/
|
||||
private void clearProductListCache() {
|
||||
Set<String> listCacheKeys = redisService.keys(PRODUCT_LIST_CACHE_PREFIX + "*");
|
||||
if (!listCacheKeys.isEmpty()) {
|
||||
if (listCacheKeys != null && !listCacheKeys.isEmpty()) {
|
||||
redisService.delete(listCacheKeys);
|
||||
}
|
||||
redisService.delete(HOT_PRODUCTS_CACHE);
|
||||
@@ -495,8 +496,15 @@ public class ProductService {
|
||||
log.info("删除商品: {}", productId);
|
||||
|
||||
try {
|
||||
// 删除数据库记录
|
||||
productRepository.deleteById(productId);
|
||||
Optional<Product> productOpt = productRepository.findById(productId);
|
||||
if (!productOpt.isPresent()) {
|
||||
log.warn("删除商品失败,商品不存在: {}", productId);
|
||||
return false;
|
||||
}
|
||||
|
||||
Product product = productOpt.get();
|
||||
product.setStatus(0);
|
||||
productRepository.save(product);
|
||||
|
||||
// 删除相关缓存
|
||||
String productCacheKey = PRODUCT_CACHE_PREFIX + productId;
|
||||
@@ -509,8 +517,9 @@ public class ProductService {
|
||||
|
||||
// 清除商品列表缓存
|
||||
clearProductListCache();
|
||||
redisService.delete(ACTIVE_FLASH_SALES_CACHE);
|
||||
|
||||
log.info("商品删除成功: {}", productId);
|
||||
log.info("商品已下架: {}", productId);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error("删除商品失败: {}", productId, e);
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.org.flashsalesystem.service;
|
||||
|
||||
import com.org.flashsalesystem.entity.Product;
|
||||
import com.org.flashsalesystem.repository.ProductRepository;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@DisplayName("商品服务测试")
|
||||
class ProductServiceTest {
|
||||
|
||||
@Mock
|
||||
private ProductRepository productRepository;
|
||||
|
||||
@Mock
|
||||
private RedisService redisService;
|
||||
|
||||
@InjectMocks
|
||||
private ProductService productService;
|
||||
|
||||
@Test
|
||||
@DisplayName("删除商品 - 改为下架以保留历史引用")
|
||||
void deleteProduct_MarksProductInactive() {
|
||||
Product product = new Product();
|
||||
product.setId(1L);
|
||||
product.setName("测试商品");
|
||||
product.setPrice(new BigDecimal("19.90"));
|
||||
product.setStock(10);
|
||||
product.setStatus(1);
|
||||
|
||||
when(productRepository.findById(1L)).thenReturn(Optional.of(product));
|
||||
when(productRepository.save(any(Product.class))).thenAnswer(invocation -> invocation.getArgument(0));
|
||||
when(redisService.keys(anyString())).thenReturn(Collections.emptySet());
|
||||
|
||||
boolean result = productService.deleteProduct(1L);
|
||||
|
||||
assertTrue(result);
|
||||
assertEquals(0, product.getStatus());
|
||||
verify(productRepository).save(product);
|
||||
verify(productRepository, never()).deleteById(1L);
|
||||
verify(redisService).delete("product:" + 1L);
|
||||
verify(redisService).delete("product_stock:" + 1L);
|
||||
verify(redisService).zRem("product_sales_rank", 1L);
|
||||
verify(redisService).delete("active_flashsales");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("删除商品 - 商品不存在")
|
||||
void deleteProduct_ProductNotFound() {
|
||||
when(productRepository.findById(404L)).thenReturn(Optional.empty());
|
||||
|
||||
boolean result = productService.deleteProduct(404L);
|
||||
|
||||
assertFalse(result);
|
||||
verify(productRepository, never()).save(any(Product.class));
|
||||
verify(productRepository, never()).deleteById(404L);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user