砍价过期逻辑 补充和优化
This commit is contained in:
parent
528c76a912
commit
db5bd06c35
@ -11,7 +11,6 @@ import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@ -492,7 +491,7 @@ public class DateTimeUtils {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断指定时间是否在两个时间点之间(包含边界)
|
||||
*
|
||||
@ -602,6 +601,27 @@ public class DateTimeUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isActivityTimeValid(Date starTime, Date endTime, Date checkTime) {
|
||||
log.debug("检查活动时间有效性 - 开始时间: {}, 结束时间: {}, 检查时间: {}", starTime, endTime, checkTime);
|
||||
|
||||
if (starTime == null || endTime == null) {
|
||||
log.error("活动时间验证失败 - 开始时间或结束时间为null. 开始时间: {}, 结束时间: {}", starTime, endTime);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (checkTime == null) {
|
||||
checkTime = new Date();
|
||||
log.warn("检查时间为空,使用当前时间: {}", checkTime);
|
||||
}
|
||||
|
||||
boolean isValid = !checkTime.before(starTime) && !checkTime.after(endTime);
|
||||
log.debug("活动时间验证结果: {} (检查时间>=开始时间, 检查时间<=结束时间)",
|
||||
isValid);
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
// System.out.println(convertLklDate("2021-02-19")); // 2025-01-02
|
||||
// System.out.println(convertLklDate("2021-2-3")); // 2025-01-02
|
||||
@ -632,29 +652,29 @@ public class DateTimeUtils {
|
||||
|
||||
// System.out.println("当前时间是否在工作时间内:" + isWorkTime);
|
||||
// System.out.println("多个时间段的交集结果:" + isNight);
|
||||
|
||||
System.out.println("=== 测试 findTimeIntersection ===");
|
||||
|
||||
// 测试正常交集情况
|
||||
List<Pair<String, String>> timeList1 = new ArrayList<>();
|
||||
timeList1.add(Pair.of("06:00", "17:00"));
|
||||
timeList1.add(Pair.of("10:00", "18:00"));
|
||||
|
||||
Pair<String, String> intersection1 = findTimeInterSection(timeList1);
|
||||
System.out.println("交集结果1: " + intersection1); // 应该是 10:00 - 17:00
|
||||
|
||||
// 测试无交集情况
|
||||
List<Pair<String, String>> timeList2 = new ArrayList<>();
|
||||
timeList2.add(Pair.of("09:00", "12:00"));
|
||||
timeList2.add(Pair.of("13:00", "17:00"));
|
||||
|
||||
Pair<String, String> intersection2 = findTimeInterSection(timeList2);
|
||||
System.out.println("交集结果2: " + intersection2); // 应该是null
|
||||
|
||||
// 测试空列表
|
||||
Pair<String, String> intersection3 = findTimeInterSection(null);
|
||||
System.out.println("交集结果3 (null输入): " + intersection3); // 应该是null
|
||||
|
||||
//
|
||||
// System.out.println("=== 测试 findTimeIntersection ===");
|
||||
//
|
||||
// // 测试正常交集情况
|
||||
// List<Pair<String, String>> timeList1 = new ArrayList<>();
|
||||
// timeList1.add(Pair.of("06:00", "17:00"));
|
||||
// timeList1.add(Pair.of("10:00", "18:00"));
|
||||
//
|
||||
// Pair<String, String> intersection1 = findTimeInterSection(timeList1);
|
||||
// System.out.println("交集结果1: " + intersection1); // 应该是 10:00 - 17:00
|
||||
//
|
||||
//// 测试无交集情况
|
||||
// List<Pair<String, String>> timeList2 = new ArrayList<>();
|
||||
// timeList2.add(Pair.of("09:00", "12:00"));
|
||||
// timeList2.add(Pair.of("13:00", "17:00"));
|
||||
//
|
||||
// Pair<String, String> intersection2 = findTimeInterSection(timeList2);
|
||||
// System.out.println("交集结果2: " + intersection2); // 应该是null
|
||||
//
|
||||
//// 测试空列表
|
||||
// Pair<String, String> intersection3 = findTimeInterSection(null);
|
||||
// System.out.println("交集结果3 (null输入): " + intersection3); // 应该是null
|
||||
//
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,349 @@
|
||||
package com.suisung.mall.common.utils;
|
||||
|
||||
import com.suisung.mall.core.web.service.RedisService;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* DistributedLockHelper综合测试套件
|
||||
*/
|
||||
public class DistributedLockHelperTest {
|
||||
|
||||
private DistributedLockHelper lockHelper;
|
||||
|
||||
@Mock
|
||||
private RedisService redisService;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
lockHelper = new DistributedLockHelper();
|
||||
ReflectionTestUtils.setField(lockHelper, "redisService", redisService);
|
||||
System.out.println("=== 初始化测试环境 ===");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTryLock_Success() {
|
||||
System.out.println("开始执行: testTryLock_Success");
|
||||
|
||||
// 给定条件
|
||||
String lockKey = "test_lock";
|
||||
long expireTimeSec = 30L;
|
||||
String expectedKey = "distributed_lock:" + lockKey;
|
||||
System.out.println("测试参数 - 锁键: " + lockKey + ", 过期时间: " + expireTimeSec + "秒");
|
||||
|
||||
// 当调用时
|
||||
when(redisService.set(anyString(), anyString(), anyLong())).thenReturn(true);
|
||||
boolean result = lockHelper.tryLock(lockKey, expireTimeSec);
|
||||
System.out.println("获取锁结果: " + (result ? "成功" : "失败"));
|
||||
|
||||
// 那么验证
|
||||
assertTrue(result, "锁应该成功获取");
|
||||
verify(redisService).set(eq(expectedKey), anyString(), eq(expireTimeSec));
|
||||
System.out.println("验证通过: Redis set 方法被正确调用");
|
||||
System.out.println("测试完成: testTryLock_Success\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTryLock_Failure() {
|
||||
System.out.println("开始执行: testTryLock_Failure");
|
||||
|
||||
// 给定条件
|
||||
String lockKey = "test_lock";
|
||||
long expireTimeSec = 30L;
|
||||
System.out.println("测试参数 - 锁键: " + lockKey + ", 过期时间: " + expireTimeSec + "秒");
|
||||
|
||||
// 当调用时
|
||||
when(redisService.set(anyString(), anyString(), anyLong())).thenThrow(new RuntimeException("Redis错误"));
|
||||
System.out.println("模拟Redis异常: Redis错误");
|
||||
|
||||
// 那么验证
|
||||
assertThrows(RuntimeException.class, () -> {
|
||||
lockHelper.tryLock(lockKey, expireTimeSec);
|
||||
}, "应该抛出RuntimeException");
|
||||
System.out.println("验证通过: 正确捕获了RuntimeException");
|
||||
System.out.println("测试完成: testTryLock_Failure\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReleaseLock_Success() {
|
||||
System.out.println("开始执行: testReleaseLock_Success");
|
||||
|
||||
// 给定条件
|
||||
String lockKey = "test_lock";
|
||||
String expectedKey = "distributed_lock:" + lockKey;
|
||||
String lockValue = "uuid:1";
|
||||
System.out.println("测试参数 - 锁键: " + lockKey + ", 锁值: " + lockValue);
|
||||
|
||||
// 设置线程本地变量
|
||||
ReflectionTestUtils.setField(lockHelper, "LOCK_VALUE_HOLDER",
|
||||
new ThreadLocal<String>() {
|
||||
@Override
|
||||
protected String initialValue() {
|
||||
return lockValue;
|
||||
}
|
||||
});
|
||||
|
||||
when(redisService.get(expectedKey)).thenReturn(lockValue);
|
||||
System.out.println("模拟Redis get返回值: " + lockValue);
|
||||
|
||||
// 当调用时
|
||||
lockHelper.releaseLock(lockKey);
|
||||
System.out.println("执行锁释放操作");
|
||||
|
||||
// 那么验证
|
||||
verify(redisService).del(expectedKey);
|
||||
System.out.println("验证通过: Redis del 方法被正确调用");
|
||||
System.out.println("测试完成: testReleaseLock_Success\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReleaseLock_WrongOwner() {
|
||||
System.out.println("开始执行: testReleaseLock_WrongOwner");
|
||||
|
||||
// 给定条件
|
||||
String lockKey = "test_lock";
|
||||
String expectedKey = "distributed_lock:" + lockKey;
|
||||
String currentValue = "uuid:1";
|
||||
String threadValue = "uuid:2"; // 不同的值
|
||||
System.out.println("测试参数 - 当前锁值: " + currentValue + ", 线程锁值: " + threadValue);
|
||||
|
||||
// 设置线程本地变量
|
||||
ReflectionTestUtils.setField(lockHelper, "LOCK_VALUE_HOLDER",
|
||||
new ThreadLocal<String>() {
|
||||
@Override
|
||||
protected String initialValue() {
|
||||
return threadValue;
|
||||
}
|
||||
});
|
||||
|
||||
when(redisService.get(expectedKey)).thenReturn(currentValue);
|
||||
System.out.println("模拟Redis中当前锁值: " + currentValue);
|
||||
|
||||
// 当调用时
|
||||
lockHelper.releaseLock(lockKey);
|
||||
System.out.println("执行锁释放操作");
|
||||
|
||||
// 那么验证
|
||||
verify(redisService, never()).del(anyString());
|
||||
System.out.println("验证通过: Redis del 方法未被调用(防止误删)");
|
||||
System.out.println("测试完成: testReleaseLock_WrongOwner\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcurrentAccess_SingleLockAcquirer() throws InterruptedException {
|
||||
System.out.println("开始执行: testConcurrentAccess_SingleLockAcquirer");
|
||||
|
||||
// 给定条件
|
||||
String lockKey = "concurrent_test_lock";
|
||||
int threadCount = 10;
|
||||
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
|
||||
CountDownLatch latch = new CountDownLatch(threadCount);
|
||||
AtomicInteger successCounter = new AtomicInteger(0);
|
||||
System.out.println("测试参数 - 并发线程数: " + threadCount + ", 锁键: " + lockKey);
|
||||
|
||||
// 模拟Redis并发访问行为
|
||||
when(redisService.set(anyString(), anyString(), anyLong()))
|
||||
.thenAnswer(invocation -> {
|
||||
// 只有第一次调用成功,其余都失败
|
||||
boolean result = successCounter.get() == 0;
|
||||
if (result) {
|
||||
System.out.println("线程[" + Thread.currentThread().getName() + "] 成功获取锁");
|
||||
}
|
||||
return result;
|
||||
});
|
||||
System.out.println("模拟Redis行为: 只允许一个线程获取锁");
|
||||
|
||||
// 当执行时
|
||||
for (int i = 0; i < threadCount; i++) {
|
||||
final int threadId = i;
|
||||
executor.submit(() -> {
|
||||
try {
|
||||
System.out.println("启动线程[" + threadId + "]");
|
||||
if (lockHelper.tryLock(lockKey, 30)) {
|
||||
int count = successCounter.incrementAndGet();
|
||||
System.out.println("线程[" + threadId + "] 获取锁成功,当前成功计数: " + count);
|
||||
lockHelper.releaseLock(lockKey);
|
||||
System.out.println("线程[" + threadId + "] 释放锁");
|
||||
} else {
|
||||
System.out.println("线程[" + threadId + "] 获取锁失败");
|
||||
}
|
||||
} finally {
|
||||
latch.countDown();
|
||||
System.out.println("线程[" + threadId + "] 执行完毕,剩余线程数: " + (latch.getCount()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
boolean completed = latch.await(5, TimeUnit.SECONDS);
|
||||
executor.shutdown();
|
||||
System.out.println("所有线程执行完成: " + (completed ? "正常结束" : "超时结束"));
|
||||
|
||||
// 那么验证
|
||||
int successCount = successCounter.get();
|
||||
assertEquals(1, successCount, "应该只有一个线程获得锁");
|
||||
System.out.println("验证通过: 实际成功获取锁的线程数为 " + successCount);
|
||||
System.out.println("测试完成: testConcurrentAccess_SingleLockAcquirer\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutoRenewalFunctionality() throws InterruptedException {
|
||||
System.out.println("开始执行: testAutoRenewalFunctionality");
|
||||
|
||||
// 给定条件
|
||||
String lockKey = "auto_renew_test_lock";
|
||||
long expireTimeSec = 5L;
|
||||
long maxHoldTimeSec = 10L;
|
||||
System.out.println("测试参数 - 锁键: " + lockKey + ", 过期时间: " + expireTimeSec + "秒, 最大持有时间: " + maxHoldTimeSec + "秒");
|
||||
|
||||
when(redisService.set(anyString(), anyString(), anyLong())).thenReturn(true);
|
||||
when(redisService.get(anyString())).thenReturn("mock-value");
|
||||
System.out.println("模拟Redis set/get操作成功");
|
||||
|
||||
// 当调用时
|
||||
DistributedLockHelper.LockHolder lockHolder =
|
||||
lockHelper.tryLockWithAutoRenew(lockKey, expireTimeSec, maxHoldTimeSec);
|
||||
System.out.println("获取带自动续期功能的锁");
|
||||
|
||||
assertNotNull(lockHolder, "锁持有者不应为空");
|
||||
System.out.println("锁持有者创建成功");
|
||||
|
||||
// 等待可能的续期操作
|
||||
System.out.println("等待3秒观察自动续期行为...");
|
||||
Thread.sleep(3000);
|
||||
|
||||
// 那么验证
|
||||
verify(redisService, atLeastOnce()).expire(anyString(), anyLong());
|
||||
System.out.println("验证通过: Redis expire 方法至少被调用一次");
|
||||
|
||||
// 清理
|
||||
lockHolder.close();
|
||||
System.out.println("关闭锁持有者,清理资源");
|
||||
System.out.println("测试完成: testAutoRenewalFunctionality\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLockHolderAutoClose() {
|
||||
System.out.println("开始执行: testLockHolderAutoClose");
|
||||
|
||||
// 给定条件
|
||||
String lockKey = "auto_close_test_lock";
|
||||
System.out.println("测试参数 - 锁键: " + lockKey);
|
||||
|
||||
when(redisService.set(anyString(), anyString(), anyLong())).thenReturn(true);
|
||||
when(redisService.get(anyString())).thenReturn("mock-value");
|
||||
System.out.println("模拟Redis操作成功");
|
||||
|
||||
// 当调用时
|
||||
System.out.println("使用try-with-resources语法获取锁");
|
||||
try (DistributedLockHelper.LockHolder holder =
|
||||
lockHelper.tryLockWithAutoRenew(lockKey, 30, 300)) {
|
||||
assertNotNull(holder, "锁持有者不应为空");
|
||||
System.out.println("锁持有者创建成功");
|
||||
}
|
||||
System.out.println("try-with-resources块结束,自动调用close方法");
|
||||
|
||||
// 那么验证
|
||||
verify(redisService).del(anyString());
|
||||
System.out.println("验证通过: Redis del 方法被正确调用");
|
||||
System.out.println("测试完成: testLockHolderAutoClose\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleLocksIndependence() {
|
||||
System.out.println("开始执行: testMultipleLocksIndependence");
|
||||
|
||||
// 给定条件
|
||||
String lockKey1 = "lock_1";
|
||||
String lockKey2 = "lock_2";
|
||||
System.out.println("测试参数 - 锁键1: " + lockKey1 + ", 锁键2: " + lockKey2);
|
||||
|
||||
when(redisService.set(anyString(), anyString(), anyLong())).thenReturn(true);
|
||||
System.out.println("模拟Redis set操作成功");
|
||||
|
||||
// 当调用时
|
||||
boolean lock1Acquired = lockHelper.tryLock(lockKey1, 30);
|
||||
System.out.println("获取第一个锁: " + (lock1Acquired ? "成功" : "失败"));
|
||||
|
||||
boolean lock2Acquired = lockHelper.tryLock(lockKey2, 30);
|
||||
System.out.println("获取第二个锁: " + (lock2Acquired ? "成功" : "失败"));
|
||||
|
||||
// 那么验证
|
||||
assertTrue(lock1Acquired, "第一个锁应该成功获取");
|
||||
assertTrue(lock2Acquired, "第二个锁应该成功获取");
|
||||
System.out.println("两个锁都成功获取");
|
||||
|
||||
// 验证它们是不同的键
|
||||
verify(redisService).set(eq("distributed_lock:" + lockKey1), anyString(), eq(30L));
|
||||
verify(redisService).set(eq("distributed_lock:" + lockKey2), anyString(), eq(30L));
|
||||
System.out.println("验证通过: 两个独立的锁键都被正确设置");
|
||||
System.out.println("测试完成: testMultipleLocksIndependence\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThreadIsolation() throws InterruptedException {
|
||||
System.out.println("开始执行: testThreadIsolation");
|
||||
|
||||
// 给定条件
|
||||
String lockKey = "thread_isolation_lock";
|
||||
ExecutorService executor = Executors.newFixedThreadPool(2);
|
||||
CountDownLatch latch = new CountDownLatch(2);
|
||||
AtomicInteger[] results = new AtomicInteger[]{new AtomicInteger(0), new AtomicInteger(0)};
|
||||
System.out.println("测试参数 - 锁键: " + lockKey + ", 线程数: 2");
|
||||
|
||||
when(redisService.set(anyString(), anyString(), anyLong())).thenReturn(true);
|
||||
System.out.println("模拟Redis set操作成功");
|
||||
|
||||
// 当执行时
|
||||
System.out.println("启动两个线程竞争同一个锁");
|
||||
for (int i = 0; i < 2; i++) {
|
||||
final int threadIndex = i;
|
||||
executor.submit(() -> {
|
||||
try {
|
||||
System.out.println("线程[" + threadIndex + "] 尝试获取锁");
|
||||
if (lockHelper.tryLock(lockKey, 30)) {
|
||||
int count = results[threadIndex].incrementAndGet();
|
||||
System.out.println("线程[" + threadIndex + "] 获取锁成功,计数: " + count);
|
||||
// 持有锁一段时间
|
||||
Thread.sleep(100);
|
||||
System.out.println("线程[" + threadIndex + "] 持有锁100ms后释放");
|
||||
lockHelper.releaseLock(lockKey);
|
||||
System.out.println("线程[" + threadIndex + "] 释放锁");
|
||||
} else {
|
||||
System.out.println("线程[" + threadIndex + "] 获取锁失败");
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("线程[" + threadIndex + "] 被中断");
|
||||
Thread.currentThread().interrupt();
|
||||
} finally {
|
||||
latch.countDown();
|
||||
System.out.println("线程[" + threadIndex + "] 执行完毕");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
boolean completed = latch.await(5, TimeUnit.SECONDS);
|
||||
executor.shutdown();
|
||||
System.out.println("所有线程执行完成: " + (completed ? "正常结束" : "超时结束"));
|
||||
|
||||
// 那么验证 - 两个线程都应该能够在不同时间获得锁
|
||||
int result0 = results[0].get();
|
||||
int result1 = results[1].get();
|
||||
assertEquals(1, result0, "线程0应该获得一次锁");
|
||||
assertEquals(1, result1, "线程1应该获得一次锁");
|
||||
System.out.println("验证通过: 线程0获得锁次数=" + result0 + ", 线程1获得锁次数=" + result1);
|
||||
System.out.println("测试完成: testThreadIsolation\n");
|
||||
}
|
||||
}
|
||||
@ -33,11 +33,11 @@ public interface ShopActivityCutpriceService extends IBaseService<ShopActivityCu
|
||||
/**
|
||||
* 砍价活动是否可以下单
|
||||
*
|
||||
* @param ac_id 活动 自增Id
|
||||
* @param activity_id 活动 自增Id
|
||||
* @param order_user_id 下单用户
|
||||
* @return
|
||||
*/
|
||||
Pair<Boolean, String> canDoOrderCutPriceActivity(Integer ac_id, Integer order_user_id);
|
||||
Pair<Boolean, String> canDoOrderCutPriceActivity(Integer activity_id, Integer order_user_id);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -25,6 +25,7 @@ import com.suisung.mall.common.modules.activity.ShopActivityGroupbooking;
|
||||
import com.suisung.mall.common.modules.activity.ShopActivityGroupbookingHistory;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreActivityBase;
|
||||
import com.suisung.mall.common.utils.CheckUtil;
|
||||
import com.suisung.mall.common.utils.DateTimeUtils;
|
||||
import com.suisung.mall.common.utils.I18nUtil;
|
||||
import com.suisung.mall.core.web.service.RedisService;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
@ -314,7 +315,7 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl<ShopActivit
|
||||
// 如果用户未参与该砍价活动,则创建新的砍价记录
|
||||
if (cutprice_row == null) {
|
||||
|
||||
if (!checkStockResult.getFirst()) {
|
||||
if (checkStockResult != null && !checkStockResult.getFirst()) {
|
||||
// 库存不够,立即更改活动状态为已结束
|
||||
shopStoreActivityBaseService.updateActivityState(activity_id, StateCode.ACTIVITY_STATE_FINISHED);
|
||||
throw new ApiException(checkStockResult.getSecond());
|
||||
@ -377,9 +378,11 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl<ShopActivit
|
||||
// 设置活动规则信息
|
||||
activity_row.put("activity_rule", JSONUtil.parseObj(activity_row.get("activity_rule")));
|
||||
|
||||
if (!checkStockResult.getFirst()) {
|
||||
if (checkStockResult != null && !checkStockResult.getFirst()) {
|
||||
// 库存不够,立即更改活动状态为已结束
|
||||
shopStoreActivityBaseService.updateActivityState(activity_id, StateCode.ACTIVITY_STATE_FINISHED);
|
||||
activity_row.put("can_buy_now", CommonConstant.Disable2);
|
||||
activity_row.put("cannot_buy_now_reason", "抱歉,您慢了一步,商品已抢空!");
|
||||
activity_row.put("cannot_buy_now_reason", "抱歉,商品已抢空,活动已结束");
|
||||
} else {
|
||||
// 判断是否可以立即购买
|
||||
boolean canBuyNow = cutprice_row != null
|
||||
@ -618,7 +621,7 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl<ShopActivit
|
||||
}
|
||||
|
||||
// 2. 检查活动是否在有效期内
|
||||
if (!shopStoreActivityBaseService.isActivityTimeValid(storeActivityBase.getActivity_starttime(), storeActivityBase.getActivity_endtime(), new Date())) {
|
||||
if (!DateTimeUtils.isActivityTimeValid(storeActivityBase.getActivity_starttime(), storeActivityBase.getActivity_endtime(), new Date())) {
|
||||
return Pair.of(false, I18nUtil._("该活动已过期,请检查。"));
|
||||
}
|
||||
|
||||
@ -686,7 +689,7 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl<ShopActivit
|
||||
}
|
||||
|
||||
// 检查活动是否过期
|
||||
boolean isActivityTimeValid = shopStoreActivityBaseService.isActivityTimeValid(
|
||||
boolean isActivityTimeValid = DateTimeUtils.isActivityTimeValid(
|
||||
shopStoreActivityBase.getActivity_starttime(),
|
||||
shopStoreActivityBase.getActivity_endtime(),
|
||||
new Date()
|
||||
|
||||
@ -5,6 +5,7 @@ import cn.hutool.core.convert.Convert;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.suisung.mall.common.api.StateCode;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreActivityBase;
|
||||
import com.suisung.mall.common.utils.DateTimeUtils;
|
||||
import com.suisung.mall.shop.activity.service.ShopActivityCutpriceService;
|
||||
import com.suisung.mall.shop.config.SpringUtil;
|
||||
import com.suisung.mall.shop.store.service.ShopStoreActivityBaseService;
|
||||
@ -28,33 +29,57 @@ public class UpdateActivityStatusJob extends QuartzJobBean {
|
||||
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
|
||||
Logger logger = LoggerFactory.getLogger(UpdateActivityStatusJob.class);
|
||||
ShopStoreActivityBaseService shopStoreActivityBaseService = SpringUtil.getBean(ShopStoreActivityBaseService.class);
|
||||
ShopActivityCutpriceService shopActivityCutpriceService = SpringUtil.getBean(ShopActivityCutpriceService.class);
|
||||
TransactionTemplate transactionTemplate = SpringUtil.getBean(TransactionTemplate.class);
|
||||
|
||||
int page = 1;
|
||||
List<ShopStoreActivityBase> activityBaseList;
|
||||
QueryWrapper<ShopStoreActivityBase> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("activity_state", StateCode.ACTIVITY_STATE_WAITING);
|
||||
queryWrapper.le("activity_starttime", new Date());
|
||||
queryWrapper.in("activity_state", StateCode.ACTIVITY_STATE_WAITING, StateCode.ACTIVITY_STATE_NORMAL);
|
||||
// queryWrapper.le("activity_starttime", new Date());
|
||||
|
||||
while (CollUtil.isNotEmpty(activityBaseList = shopStoreActivityBaseService.lists(queryWrapper, page, 20).getRecords())) {
|
||||
for (ShopStoreActivityBase storeActivityBase : activityBaseList) {
|
||||
if (storeActivityBase.getActivity_state() != null
|
||||
&& storeActivityBase.getActivity_state().intValue() == StateCode.ACTIVITY_STATE_WAITING
|
||||
&& DateTimeUtils.isActivityTimeValid(storeActivityBase.getActivity_starttime(), storeActivityBase.getActivity_endtime(), new Date())) {
|
||||
Boolean result = transactionTemplate.execute(status -> {
|
||||
storeActivityBase.setActivity_state(StateCode.ACTIVITY_STATE_NORMAL);
|
||||
Map<String, Object> activityBaseMap = Convert.toMap(String.class, Object.class, storeActivityBase);
|
||||
|
||||
Boolean result = transactionTemplate.execute(status -> {
|
||||
storeActivityBase.setActivity_state(StateCode.ACTIVITY_STATE_NORMAL);
|
||||
Map<String, Object> activityBaseMap = Convert.toMap(String.class, Object.class, storeActivityBase);
|
||||
if (!shopStoreActivityBaseService.editActivityBase(storeActivityBase.getActivity_id(), activityBaseMap)) {
|
||||
status.isRollbackOnly();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!shopStoreActivityBaseService.editActivityBase(storeActivityBase.getActivity_id(), activityBaseMap)) {
|
||||
status.isRollbackOnly();
|
||||
return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
if (Boolean.FALSE.equals(result)) {
|
||||
logger.error(String.format("activity_id : %s 开启出错", storeActivityBase.getActivity_id()));
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if (Boolean.FALSE.equals(result)) {
|
||||
logger.error(String.format("activity_id : %s 开启出错", storeActivityBase.getActivity_id()));
|
||||
}
|
||||
|
||||
if (storeActivityBase.getActivity_state() != null
|
||||
&& storeActivityBase.getActivity_state().intValue() == StateCode.ACTIVITY_STATE_NORMAL
|
||||
&& !DateTimeUtils.isActivityTimeValid(storeActivityBase.getActivity_starttime(), storeActivityBase.getActivity_endtime(), new Date())) {
|
||||
|
||||
Boolean result = transactionTemplate.execute(status -> {
|
||||
storeActivityBase.setActivity_state(StateCode.ACTIVITY_STATE_FINISHED);
|
||||
Map<String, Object> activityBaseMap = Convert.toMap(String.class, Object.class, storeActivityBase);
|
||||
|
||||
if (!shopStoreActivityBaseService.editActivityBase(storeActivityBase.getActivity_id(), activityBaseMap)) {
|
||||
status.isRollbackOnly();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if (Boolean.FALSE.equals(result)) {
|
||||
logger.error(String.format("activity_id : %s 设置过期出错", storeActivityBase.getActivity_id()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
@ -65,8 +90,18 @@ public class UpdateActivityStatusJob extends QuartzJobBean {
|
||||
page++;
|
||||
}
|
||||
|
||||
// 砍价活动时间到,更新砍价订单的过期状态
|
||||
autoUpdateCutPriceStateJob();
|
||||
}
|
||||
|
||||
/**
|
||||
* 只针对:砍价活动时间到,更新砍价订单的过期状态
|
||||
*/
|
||||
private void autoUpdateCutPriceStateJob() {
|
||||
ShopActivityCutpriceService shopActivityCutpriceService = SpringUtil.getBean(ShopActivityCutpriceService.class);
|
||||
// 活动时间到更新砍价订单的过期状态
|
||||
shopActivityCutpriceService.autoUpdateCutPriceStateJob();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -1607,6 +1607,29 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
}
|
||||
}
|
||||
|
||||
// 判断是否砍价购买
|
||||
Integer acId = getParameter("ac_id", Integer.class);
|
||||
// 判断是否为砍价活动
|
||||
Boolean isCutPriceActivity = shopStoreActivityBaseService.isCutPriceActivity(activityId);
|
||||
if (CheckUtil.isNotEmpty(activityId) && isCutPriceActivity) {
|
||||
// 判断砍价商品库存是否已售罄?
|
||||
if (shopStoreActivityBaseService.isActProdSoldOut(activityId)) {
|
||||
logger.error("检查商品库存:{}", activityId);
|
||||
throw new ApiException(I18nUtil._("砍价商品已售罄,请选择其他商品。"));
|
||||
}
|
||||
|
||||
// 校验砍价活动,用户是否可以立即购买了?
|
||||
Pair<Boolean, String> canDoOrderCutPriceActivity = shopActivityCutpriceService.canDoOrderCutPriceActivity(activityId, userId);
|
||||
if (!canDoOrderCutPriceActivity.getFirst()) {
|
||||
logger.error("检查活动是否达标:{}", canDoOrderCutPriceActivity.getSecond());
|
||||
throw new ApiException(I18nUtil._("活动已过期或未砍到底价,暂无法提交订单。"));
|
||||
}
|
||||
|
||||
cartData.put("ac_id", acId); // shop_activity_cutprice 活动参与记录的自增id
|
||||
cartData.put("activity_id", activityId);
|
||||
cartData.put("activity_type", StateCode.ACTIVITY_TYPE_CUTPRICE);
|
||||
}
|
||||
|
||||
|
||||
// 添加保存订单(关键方法)
|
||||
List<String> orderIdRow = addOrder(cartData, true, false, null);
|
||||
@ -1632,25 +1655,6 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
// cartData.put("packing_fee", packingFee);
|
||||
// }
|
||||
|
||||
// 判断是否砍价购买
|
||||
Integer acId = getParameter("ac_id", Integer.class);
|
||||
// 判断是否为砍价活动
|
||||
Boolean isCutPriceActivity = shopStoreActivityBaseService.isCutPriceActivity(activityId);
|
||||
if (CheckUtil.isNotEmpty(acId) && isCutPriceActivity) {
|
||||
cartData.put("ac_id", acId); // shop_activity_cutprice 活动参与记录的自增id
|
||||
|
||||
// 判断砍价商品库存是否已售罄?
|
||||
if (shopStoreActivityBaseService.isActProdSoldOut(activityId)) {
|
||||
throw new ApiException(I18nUtil._("砍价商品已售罄,请选择其他商品。"));
|
||||
}
|
||||
|
||||
// 校验砍价活动,用户是否可以立即购买了?
|
||||
Pair<Boolean, String> canDoOrderCutPriceActivity = shopActivityCutpriceService.canDoOrderCutPriceActivity(acId, userId);
|
||||
if (!canDoOrderCutPriceActivity.getFirst()) {
|
||||
logger.error(canDoOrderCutPriceActivity.getSecond());
|
||||
throw new ApiException(I18nUtil._("砍价活动未达标,请继续努力,再提交订单。"));
|
||||
}
|
||||
}
|
||||
|
||||
// 判断是否拼团购买
|
||||
if (gbId != null) {
|
||||
@ -6680,6 +6684,10 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
info_row.setCoupon_type_id(shopProductIndex.getCoupon_type_id());
|
||||
}
|
||||
|
||||
// 保存活动id和类型
|
||||
info_row.setActivity_id(Convert.toStr(cart_data.get("activity_id"), "0"));
|
||||
info_row.setActivity_type_id(Convert.toStr(cart_data.get("activity_type_id"), "0"));
|
||||
|
||||
// 预约订单检测
|
||||
Integer bookingState = Convert.toInt(getParameter("booking_state"));
|
||||
if (CheckUtil.isNotEmpty(bookingState) && CommonConstant.Order_Booking_State_YY.equals(bookingState)) {
|
||||
|
||||
@ -69,15 +69,15 @@ public interface ShopStoreActivityBaseService extends IBaseService<ShopStoreActi
|
||||
*/
|
||||
boolean isActivityTimeValid(ShopStoreActivityBase shopStoreActivityBase, Date checkTime);
|
||||
|
||||
/**
|
||||
* 验证活动时间是否有效
|
||||
*
|
||||
* @param starTime 活动开始时间
|
||||
* @param endTime 活动结束时间
|
||||
* @param checkTime 待验证时间
|
||||
* @return 时间是否有效
|
||||
*/
|
||||
boolean isActivityTimeValid(Date starTime, Date endTime, Date checkTime);
|
||||
// /**
|
||||
// * 验证活动时间是否有效
|
||||
// *
|
||||
// * @param starTime 活动开始时间
|
||||
// * @param endTime 活动结束时间
|
||||
// * @param checkTime 待验证时间
|
||||
// * @return 时间是否有效
|
||||
// */
|
||||
// boolean isActivityTimeValid(Date starTime, Date endTime, Date checkTime);
|
||||
|
||||
Map listsMarketing();
|
||||
|
||||
|
||||
@ -15,6 +15,7 @@ import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.suisung.mall.common.api.CommonResult;
|
||||
import com.suisung.mall.common.api.ResultCode;
|
||||
@ -36,10 +37,7 @@ import com.suisung.mall.common.modules.product.ShopProductItem;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreActivityBase;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreActivityItem;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreBase;
|
||||
import com.suisung.mall.common.utils.CheckUtil;
|
||||
import com.suisung.mall.common.utils.I18nUtil;
|
||||
import com.suisung.mall.common.utils.StringUtils;
|
||||
import com.suisung.mall.common.utils.UserInfoService;
|
||||
import com.suisung.mall.common.utils.*;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
import com.suisung.mall.shop.activity.service.*;
|
||||
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
|
||||
@ -2095,29 +2093,38 @@ public class ShopStoreActivityBaseServiceImpl extends BaseServiceImpl<ShopStoreA
|
||||
Date starTime = shopStoreActivityBase.getActivity_starttime();
|
||||
Date endTime = shopStoreActivityBase.getActivity_endtime();
|
||||
|
||||
return isActivityTimeValid(starTime, endTime, checkTime);
|
||||
return DateTimeUtils.isActivityTimeValid(starTime, endTime, checkTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证活动时间是否有效
|
||||
*
|
||||
* @param starTime 活动开始时间
|
||||
* @param endTime 活动结束时间
|
||||
* @param checkTime 待验证时间
|
||||
* @return 时间是否有效
|
||||
*/
|
||||
@Override
|
||||
public boolean isActivityTimeValid(Date starTime, Date endTime, Date checkTime) {
|
||||
if (starTime == null || endTime == null) {
|
||||
return false;
|
||||
}
|
||||
// /**
|
||||
// * 验证活动时间是否有效
|
||||
// *
|
||||
// * @param starTime 活动开始时间
|
||||
// * @param endTime 活动结束时间
|
||||
// * @param checkTime 待验证时间
|
||||
// * @return 时间是否有效
|
||||
// */
|
||||
// @Override
|
||||
// public boolean isActivityTimeValid(Date starTime, Date endTime, Date checkTime) {
|
||||
// logger.debug("检查活动时间有效性 - 开始时间: {}, 结束时间: {}, 检查时间: {}", starTime, endTime, checkTime);
|
||||
//
|
||||
// if (starTime == null || endTime == null) {
|
||||
// logger.error("活动时间验证失败 - 开始时间或结束时间为null. 开始时间: {}, 结束时间: {}", starTime, endTime);
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// if (checkTime == null) {
|
||||
// checkTime = new Date();
|
||||
// logger.warn("检查时间为空,使用当前时间: {}", checkTime);
|
||||
// }
|
||||
//
|
||||
// boolean isValid = !checkTime.before(starTime) && !checkTime.after(endTime);
|
||||
// logger.debug("活动时间验证结果: {} (检查时间>=开始时间, 检查时间<=结束时间)",
|
||||
// isValid);
|
||||
//
|
||||
// return isValid;
|
||||
// }
|
||||
|
||||
if (checkTime == null) {
|
||||
checkTime = new Date();
|
||||
}
|
||||
|
||||
return !checkTime.before(starTime) && !checkTime.after(endTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map listsMarketing() {
|
||||
@ -4460,10 +4467,9 @@ public class ShopStoreActivityBaseServiceImpl extends BaseServiceImpl<ShopStoreA
|
||||
|
||||
try {
|
||||
// 直接使用LambdaUpdateWrapper提高性能,避免创建额外实体对象
|
||||
boolean result = lambdaUpdate()
|
||||
.eq(ShopStoreActivityBase::getActivity_id, activity_id)
|
||||
.set(ShopStoreActivityBase::getActivity_state, activity_state)
|
||||
.update();
|
||||
boolean result = update(new UpdateWrapper<ShopStoreActivityBase>()
|
||||
.eq("activity_id", activity_id)
|
||||
.set("activity_state", activity_state));
|
||||
|
||||
if (result) {
|
||||
logger.info("活动状态更新成功,活动ID: {},新状态: {}", activity_id, activity_state);
|
||||
@ -4488,26 +4494,22 @@ public class ShopStoreActivityBaseServiceImpl extends BaseServiceImpl<ShopStoreA
|
||||
public boolean isActProdSoldOut(Integer activity_id) {
|
||||
// 参数校验:检查活动ID是否有效
|
||||
if (activity_id == null || activity_id <= 0) {
|
||||
logger.warn("活动商品售完检查失败:无效的活动ID - {}", activity_id);
|
||||
logger.info("活动商品售完检查失败:无效的活动ID - {}", activity_id);
|
||||
return true; // 将无效输入视为"已售完"
|
||||
}
|
||||
|
||||
try {
|
||||
// 直接从数据库查询活动记录,只获取需要的字段以提高性能
|
||||
ShopStoreActivityBase activity = lambdaQuery()
|
||||
.select(ShopStoreActivityBase::getProduct_count) // 只查询库存字段
|
||||
.eq(ShopStoreActivityBase::getActivity_id, activity_id)
|
||||
.one();
|
||||
|
||||
ShopStoreActivityBase activity = get(activity_id);
|
||||
// 如果活动不存在,视为已售完
|
||||
if (activity == null) {
|
||||
logger.warn("活动商品售完检查:未找到活动记录,activity_id={}", activity_id);
|
||||
logger.info("活动商品售完检查:未找到活动记录,activity_id={}", activity_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 获取商品库存数量
|
||||
Integer productCount = activity.getProduct_count();
|
||||
logger.debug("活动商品库存检查:activity_id={}, 库存数量={}", activity_id, productCount);
|
||||
logger.info("活动商品库存检查:activity_id={}, 库存数量={}", activity_id, productCount);
|
||||
|
||||
// 如果库存为null或小于等于0,视为已售完
|
||||
if (productCount == null || productCount <= 0) {
|
||||
@ -4518,9 +4520,9 @@ public class ShopStoreActivityBaseServiceImpl extends BaseServiceImpl<ShopStoreA
|
||||
// 获取该活动已成功的订单数量
|
||||
long soldCount = shopOrderInfoService.fetchActivityOrderSuccessCount(
|
||||
Convert.toStr(activity_id),
|
||||
Convert.toStr(StateCode.ACTIVITY_TYPE_CUTPRICE));
|
||||
""); //Convert.toStr(StateCode.ACTIVITY_TYPE_CUTPRICE)
|
||||
|
||||
logger.debug("活动商品售完检查:activity_id={}, 已售数量={}, 库存数量={}",
|
||||
logger.info("活动商品售完检查:activity_id={}, 已售数量={}, 库存数量={}",
|
||||
activity_id, soldCount, productCount);
|
||||
|
||||
// 如果已售数量大于等于库存数量,则已售完
|
||||
@ -5209,7 +5211,7 @@ public class ShopStoreActivityBaseServiceImpl extends BaseServiceImpl<ShopStoreA
|
||||
.ge("activity_item_endtime", activity.get("activity_starttime"));
|
||||
List<ShopStoreActivityItem> item_row = shopStoreActivityItemService.find(itemQueryWrapper);
|
||||
|
||||
List<Long> item_id_row = item_row.stream().filter(s->s.getActivity_item_state().equals(StateCode.ACTIVITY_STATE_NORMAL)).map(s -> s.getItem_id()).distinct().collect(Collectors.toList());
|
||||
List<Long> item_id_row = item_row.stream().filter(s -> s.getActivity_item_state().equals(StateCode.ACTIVITY_STATE_NORMAL)).map(s -> s.getItem_id()).distinct().collect(Collectors.toList());
|
||||
List<Integer> activity_id_row = item_row.stream().map(s -> s.getActivity_id()).distinct().collect(Collectors.toList());
|
||||
|
||||
List<Long> used_id_row = new ArrayList<>();
|
||||
|
||||
@ -48,6 +48,7 @@ import com.suisung.mall.common.pojo.dto.StoreBizTimeInfoDTO;
|
||||
import com.suisung.mall.common.service.impl.BaiduMapServiceImpl;
|
||||
import com.suisung.mall.common.utils.*;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
import com.suisung.mall.shop.activity.service.ShopActivityCutpriceService;
|
||||
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseProductTagService;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseStoreCategoryService;
|
||||
@ -139,6 +140,11 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ShopStoreAnalyticsService shopStoreAnalyticsService;
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ShopActivityCutpriceService shopActivityCutpriceService;
|
||||
|
||||
@Autowired
|
||||
private AccountBaseConfigService accountBaseConfigService;
|
||||
@Autowired
|
||||
@ -1104,18 +1110,44 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
|
||||
if (CheckUtil.isNotEmpty(activity_type_id)) {
|
||||
queryWrapper.eq("activity_type_id", activity_type_id);
|
||||
} else {
|
||||
queryWrapper.in("activity_type_id", StateCode.ACTIVITY_TYPE_BARGAIN,
|
||||
queryWrapper.in("activity_type_id",
|
||||
StateCode.ACTIVITY_TYPE_BARGAIN,
|
||||
StateCode.ACTIVITY_TYPE_GIFT,
|
||||
StateCode.ACTIVITY_TYPE_LIMITED_DISCOUNT,
|
||||
StateCode.ACTIVITY_TYPE_DISCOUNT_PACKAGE,
|
||||
StateCode.ACTIVITY_TYPE_DIY_PACKAGE,
|
||||
StateCode.ACTIVITY_TYPE_REDUCTION);
|
||||
StateCode.ACTIVITY_TYPE_REDUCTION,
|
||||
StateCode.ACTIVITY_TYPE_CUTPRICE);
|
||||
}
|
||||
|
||||
// 为执行排序设置默认排序
|
||||
queryWrapper.orderByDesc("activity_id");
|
||||
|
||||
Page<ShopStoreActivityBase> lists = shopStoreActivityBaseService.lists(queryWrapper, 1, 500);
|
||||
Page<ShopStoreActivityBase> lists = shopStoreActivityBaseService.lists(queryWrapper, 1, 200);
|
||||
|
||||
// Optimized version with improved code quality and readability
|
||||
List<ShopStoreActivityBase> filteredActivities = new ArrayList<>();
|
||||
for (ShopStoreActivityBase activity : lists.getRecords()) {
|
||||
// Check if it's a cut-price activity that needs validation
|
||||
if (activity.getActivity_type_id() != null
|
||||
&& activity.getActivity_type_id() == StateCode.ACTIVITY_TYPE_CUTPRICE) {
|
||||
|
||||
// Validate cut-price activity stock and expiration
|
||||
Pair<Boolean, String> checkStockResult = shopActivityCutpriceService.checkCutPriceExpiredAndStock(activity);
|
||||
if (checkStockResult != null && !checkStockResult.getFirst()) {
|
||||
// Insufficient stock or expired - update activity state to finished
|
||||
shopStoreActivityBaseService.updateActivityState(activity.getActivity_id(), StateCode.ACTIVITY_STATE_FINISHED);
|
||||
continue; // Skip adding this activity to results
|
||||
}
|
||||
}
|
||||
|
||||
// Add valid activities to filtered list
|
||||
filteredActivities.add(activity);
|
||||
}
|
||||
|
||||
// Update the page records with filtered results
|
||||
lists.setRecords(filteredActivities);
|
||||
|
||||
|
||||
Map data = toMobileResult(lists);
|
||||
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user