Merge remote-tracking branch 'yudao/feature/mall_product' into feature/mall_product

This commit is contained in:
puhui999 2023-08-06 01:05:47 +08:00
commit afaef0dfbb
32 changed files with 345 additions and 127 deletions

View File

@ -133,6 +133,11 @@
<artifactId>transmittable-thread-local</artifactId> <artifactId>transmittable-thread-local</artifactId>
</dependency> </dependency>
<!-- Test 测试相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -6,12 +6,11 @@ import cn.hutool.core.map.MapUtil;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import java.util.*; import java.util.*;
import java.util.function.BinaryOperator; import java.util.function.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static java.util.Arrays.asList;
/** /**
* Collection 工具类 * Collection 工具类
* *
@ -20,13 +19,14 @@ import java.util.stream.Collectors;
public class CollectionUtils { public class CollectionUtils {
public static boolean containsAny(Object source, Object... targets) { public static boolean containsAny(Object source, Object... targets) {
return Arrays.asList(targets).contains(source); return asList(targets).contains(source);
} }
public static boolean isAnyEmpty(Collection<?>... collections) { public static boolean isAnyEmpty(Collection<?>... collections) {
return Arrays.stream(collections).anyMatch(CollectionUtil::isEmpty); return Arrays.stream(collections).anyMatch(CollectionUtil::isEmpty);
} }
// TODO @puhui999anyMatch 更统一点
public static <T> boolean isAny(Collection<T> from, Predicate<T> predicate) { public static <T> boolean isAny(Collection<T> from, Predicate<T> predicate) {
return from.stream().anyMatch(predicate); return from.stream().anyMatch(predicate);
} }
@ -189,6 +189,46 @@ public class CollectionUtils {
return func.apply(mapData); return func.apply(mapData);
} }
/**
* 对比老新两个列表找出新增修改删除的数据
*
* @param oldList 老列表
* @param newList 新列表
* @param sameFunc 对比函数返回 true 表示相同返回 false 表示不同
* 注意same 是通过每个元素的标识判断它们是不是同一个数据
* @return [新增列表修改列表删除列表]
*/
public static <T> List<List<T>> diffList(Collection<T> oldList, Collection<T> newList,
BiFunction<T, T, Boolean> sameFunc) {
List<T> createList = new LinkedList<>(newList); // 默认都认为是新增的后续会进行移除
List<T> updateList = new ArrayList<>();
List<T> deleteList = new ArrayList<>();
// 通过以 oldList 为主遍历找出 updateList deleteList
for (T oldObj : oldList) {
// 1. 寻找是否有匹配的
T foundObj = null;
for (Iterator<T> iterator = createList.iterator(); iterator.hasNext(); ) {
T newObj = iterator.next();
// 1.1 不匹配则直接跳过
if (!sameFunc.apply(oldObj, newObj)) {
continue;
}
// 1.2 匹配则移除并结束寻找
iterator.remove();
foundObj = newObj;
break;
}
// 2. 匹配添加到 updateList不匹配则添加到 deleteList
if (foundObj != null) {
updateList.add(foundObj);
} else {
deleteList.add(oldObj);
}
}
return asList(createList, updateList, deleteList);
}
public static boolean containsAny(Collection<?> source, Collection<?> candidates) { public static boolean containsAny(Collection<?> source, Collection<?> candidates) {
return org.springframework.util.CollectionUtils.containsAny(source, candidates); return org.springframework.util.CollectionUtils.containsAny(source, candidates);
} }

View File

@ -84,11 +84,11 @@ public class LocalDateTimeUtils {
public static boolean isOverlap(LocalTime startTime1, LocalTime endTime1, LocalTime startTime2, LocalTime endTime2) { public static boolean isOverlap(LocalTime startTime1, LocalTime endTime1, LocalTime startTime2, LocalTime endTime2) {
// 日期部分使用了当前日期LocalDate.now() // 日期部分使用了当前日期LocalDate.now()
// TODO @puhui999LocalDate.now() 抽一个变量啊哈然后注释写下之后 4 个变量不用直接调方法的时候直接计算作为入参
LocalDateTime startDateTime1 = LocalDateTime.of(LocalDate.now(), startTime1); LocalDateTime startDateTime1 = LocalDateTime.of(LocalDate.now(), startTime1);
LocalDateTime endDateTime1 = LocalDateTime.of(LocalDate.now(), endTime1); LocalDateTime endDateTime1 = LocalDateTime.of(LocalDate.now(), endTime1);
LocalDateTime startDateTime2 = LocalDateTime.of(LocalDate.now(), startTime2); LocalDateTime startDateTime2 = LocalDateTime.of(LocalDate.now(), startTime2);
LocalDateTime endDateTime2 = LocalDateTime.of(LocalDate.now(), endTime2); LocalDateTime endDateTime2 = LocalDateTime.of(LocalDate.now(), endTime2);
return LocalDateTimeUtil.isOverlap(startDateTime1, endDateTime1, startDateTime2, endDateTime2); return LocalDateTimeUtil.isOverlap(startDateTime1, endDateTime1, startDateTime2, endDateTime2);
} }

View File

@ -0,0 +1,64 @@
package cn.iocoder.yudao.framework.common.util.collection;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.BiFunction;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* {@link CollectionUtils} 的单元测试
*/
public class CollectionUtilsTest {
@Data
@AllArgsConstructor
private static class Dog {
private Integer id;
private String name;
private String code;
}
@Test
public void testDiffList() {
// 准备参数
Collection<Dog> oldList = Arrays.asList(
new Dog(1, "花花", "hh"),
new Dog(2, "旺财", "wc")
);
Collection<Dog> newList = Arrays.asList(
new Dog(null, "花花2", "hh"),
new Dog(null, "小白", "xb")
);
BiFunction<Dog, Dog, Boolean> sameFunc = (oldObj, newObj) -> {
boolean same = oldObj.getCode().equals(newObj.getCode());
// 如果相等的情况下需要设置下 id后续好更新
if (same) {
newObj.setId(oldObj.getId());
}
return same;
};
// 调用
List<List<Dog>> result = CollectionUtils.diffList(oldList, newList, sameFunc);
// 断言
assertEquals(result.size(), 3);
// 断言 create
assertEquals(result.get(0).size(), 1);
assertEquals(result.get(0).get(0), new Dog(null, "小白", "xb"));
// 断言 update
assertEquals(result.get(1).size(), 1);
assertEquals(result.get(1).get(0), new Dog(1, "花花2", "hh"));
// 断言 delete
assertEquals(result.get(2).size(), 1);
assertEquals(result.get(2).get(0), new Dog(2, "旺财", "wc"));
}
}

View File

@ -17,20 +17,18 @@ import java.util.concurrent.TimeUnit;
public class BannerApplicationRunner implements ApplicationRunner { public class BannerApplicationRunner implements ApplicationRunner {
@Override @Override
public void run(ApplicationArguments args) throws Exception { public void run(ApplicationArguments args) {
ThreadUtil.execute(() -> { ThreadUtil.execute(() -> {
ThreadUtil.sleep(1, TimeUnit.SECONDS); // 延迟 1 保证输出到结尾 ThreadUtil.sleep(1, TimeUnit.SECONDS); // 延迟 1 保证输出到结尾
log.info("\n----------------------------------------------------------\n\t" + log.info("\n----------------------------------------------------------\n\t" +
"项目启动成功!\n\t" + "项目启动成功!\n\t" +
"接口文档: \t{} \n\t" + "接口文档: \t{} \n\t" +
"开发文档: \t{} \n\t" + "开发文档: \t{} \n\t" +
"视频教程: \t{} \n\t" + "视频教程: \t{} \n" +
"源码解析: \t{} \n" +
"----------------------------------------------------------", "----------------------------------------------------------",
"https://doc.iocoder.cn/api-doc/", "https://doc.iocoder.cn/api-doc/",
"https://doc.iocoder.cn", "https://doc.iocoder.cn",
"https://t.zsxq.com/02Yf6M7Qn", "https://t.zsxq.com/02Yf6M7Qn");
"https://t.zsxq.com/02B6ujIee");
// 数据报表 // 数据报表
if (isNotPresent("cn.iocoder.yudao.module.report.framework.security.config.SecurityConfiguration")) { if (isNotPresent("cn.iocoder.yudao.module.report.framework.security.config.SecurityConfiguration")) {
@ -44,11 +42,11 @@ public class BannerApplicationRunner implements ApplicationRunner {
if (isNotPresent("cn.iocoder.yudao.module.mp.framework.mp.config.MpConfiguration")) { if (isNotPresent("cn.iocoder.yudao.module.mp.framework.mp.config.MpConfiguration")) {
System.out.println("[微信公众号 yudao-module-mp - 已禁用][参考 https://doc.iocoder.cn/mp/build/ 开启]"); System.out.println("[微信公众号 yudao-module-mp - 已禁用][参考 https://doc.iocoder.cn/mp/build/ 开启]");
} }
// 商城 // 商城系统
if (isNotPresent("cn.iocoder.yudao.module.trade.framework.web.config.TradeWebConfiguration")) { if (isNotPresent("cn.iocoder.yudao.module.trade.framework.web.config.TradeWebConfiguration")) {
System.out.println("[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]"); System.out.println("[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]");
} }
// 支付 // 支付平台
if (isNotPresent("cn.iocoder.yudao.module.pay.framework.pay.config.PayConfiguration")) { if (isNotPresent("cn.iocoder.yudao.module.pay.framework.pay.config.PayConfiguration")) {
System.out.println("[支付系统 yudao-module-pay - 已禁用][参考 https://doc.iocoder.cn/pay/build/ 开启]"); System.out.println("[支付系统 yudao-module-pay - 已禁用][参考 https://doc.iocoder.cn/pay/build/ 开启]");
} }

View File

@ -44,6 +44,12 @@ public interface BaseMapperX<T> extends BaseMapper<T> {
return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2)); return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
} }
default T selectOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2,
SFunction<T, ?> field3, Object value3) {
return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2)
.eq(field3, value3));
}
default Long selectCount() { default Long selectCount() {
return selectCount(new QueryWrapper<T>()); return selectCount(new QueryWrapper<T>());
} }

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.web.core.handler;
import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLog; import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLog;
import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService;
import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.exception.ServiceException;
@ -219,6 +220,13 @@ public class GlobalExceptionHandler {
*/ */
@ExceptionHandler(value = Exception.class) @ExceptionHandler(value = Exception.class)
public CommonResult<?> defaultExceptionHandler(HttpServletRequest req, Throwable ex) { public CommonResult<?> defaultExceptionHandler(HttpServletRequest req, Throwable ex) {
// 情况一处理表不存在的异常
CommonResult<?> tableNotExistsResult = handleTableNotExists(ex);
if (tableNotExistsResult != null) {
return tableNotExistsResult;
}
// 情况二处理异常
log.error("[defaultExceptionHandler]", ex); log.error("[defaultExceptionHandler]", ex);
// 插入异常日志 // 插入异常日志
this.createExceptionLog(req, ex); this.createExceptionLog(req, ex);
@ -269,4 +277,48 @@ public class GlobalExceptionHandler {
errorLog.setExceptionTime(LocalDateTime.now()); errorLog.setExceptionTime(LocalDateTime.now());
} }
/**
* 处理 Table 不存在的异常情况
*
* @param ex 异常
* @return 如果是 Table 不存在的异常则返回对应的 CommonResult
*/
private CommonResult<?> handleTableNotExists(Throwable ex) {
String message = ExceptionUtil.getRootCauseMessage(ex);
if (!message.contains("doesn't exist")) {
return null;
}
// 1. 数据报表
if (message.contains("report_")) {
log.error("[报表模块 yudao-module-report - 表结构未导入][参考 https://doc.iocoder.cn/report/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[报表模块 yudao-module-report - 表结构未导入][参考 https://doc.iocoder.cn/report/ 开启]");
}
// 2. 工作流
if (message.contains("bpm_")) {
log.error("[工作流模块 yudao-module-bpm - 表结构未导入][参考 https://doc.iocoder.cn/bpm/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[工作流模块 yudao-module-bpm - 表结构未导入][参考 https://doc.iocoder.cn/bpm/ 开启]");
}
// 3. 微信公众号
if (message.contains("mp_")) {
log.error("[微信公众号 yudao-module-mp - 表结构未导入][参考 https://doc.iocoder.cn/mp/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[微信公众号 yudao-module-mp - 表结构未导入][参考 https://doc.iocoder.cn/mp/build/ 开启]");
}
// 4. 商城系统
if (StrUtil.containsAny(message, "product_", "promotion_", "trade_")) {
log.error("[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]");
}
// 5. 支付平台
if (message.contains("pay_")) {
log.error("[支付模块 yudao-module-pay - 表结构未导入][参考 https://doc.iocoder.cn/pay/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[支付模块 yudao-module-pay - 表结构未导入][参考 https://doc.iocoder.cn/pay/build/ 开启]");
}
return null;
}
} }

View File

@ -1,8 +1,8 @@
package cn.iocoder.yudao.module.product.controller.app.comment; package cn.iocoder.yudao.module.product.controller.app.comment;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO; import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO; import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO;
@ -27,6 +27,7 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@Tag(name = "用户 APP - 商品评价") @Tag(name = "用户 APP - 商品评价")
@RestController @RestController
@ -56,10 +57,17 @@ public class AppProductCommentController {
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "获得商品评价分页") @Operation(summary = "获得商品评价分页")
public CommonResult<PageResult<AppProductCommentRespVO>> getCommentPage(@Valid AppCommentPageReqVO pageVO) { public CommonResult<PageResult<AppProductCommentRespVO>> getCommentPage(@Valid AppCommentPageReqVO pageVO) {
PageResult<ProductCommentDO> commentDOPage = productCommentService.getCommentPage(pageVO, Boolean.TRUE); // 查询评论分页
Set<Long> skuIds = CollectionUtils.convertSet(commentDOPage.getList(), ProductCommentDO::getSkuId); PageResult<ProductCommentDO> commentPageResult = productCommentService.getCommentPage(pageVO, Boolean.TRUE);
PageResult<AppProductCommentRespVO> page = ProductCommentConvert.INSTANCE.convertPage02(commentDOPage, productSkuService.getSkuList(skuIds)); if (CollUtil.isEmpty(commentPageResult.getList())) {
return success(page); return success(PageResult.empty(commentPageResult.getTotal()));
}
// 拼接返回
Set<Long> skuIds = convertSet(commentPageResult.getList(), ProductCommentDO::getSkuId);
PageResult<AppProductCommentRespVO> commentVOPageResult = ProductCommentConvert.INSTANCE.convertPage02(
commentPageResult, productSkuService.getSkuList(skuIds));
return success(commentVOPageResult);
} }
// TODO 芋艿需要搞下 // TODO 芋艿需要搞下

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.product.convert.comment; package cn.iocoder.yudao.module.product.convert.comment;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
@ -15,7 +14,6 @@ import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProdu
import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import com.google.common.collect.Maps;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mapping; import org.mapstruct.Mapping;
import org.mapstruct.Named; import org.mapstruct.Named;
@ -52,17 +50,16 @@ public interface ProductCommentConvert {
PageResult<AppProductCommentRespVO> convertPage01(PageResult<ProductCommentDO> pageResult); PageResult<AppProductCommentRespVO> convertPage01(PageResult<ProductCommentDO> pageResult);
default PageResult<AppProductCommentRespVO> convertPage02(PageResult<ProductCommentDO> pageResult, List<ProductSkuDO> skuList) { default PageResult<AppProductCommentRespVO> convertPage02(PageResult<ProductCommentDO> pageResult,
Map<Long, ProductSkuDO> skuMap = Maps.newLinkedHashMapWithExpectedSize(skuList.size()); List<ProductSkuDO> skuList) {
if (CollUtil.isNotEmpty(skuList)) { Map<Long, ProductSkuDO> skuMap = CollectionUtils.convertMap(skuList, ProductSkuDO::getId);
skuMap.putAll(CollectionUtils.convertMap(skuList, ProductSkuDO::getId));
}
PageResult<AppProductCommentRespVO> page = convertPage01(pageResult); PageResult<AppProductCommentRespVO> page = convertPage01(pageResult);
page.getList().forEach(item -> { page.getList().forEach(item -> {
// 判断用户是否选择匿名 // 判断用户是否选择匿名
if (ObjectUtil.equal(item.getAnonymous(), true)) { if (ObjectUtil.equal(item.getAnonymous(), true)) {
item.setUserNickname(ProductCommentDO.NICKNAME_ANONYMOUS); item.setUserNickname(ProductCommentDO.NICKNAME_ANONYMOUS);
} }
// 设置 SKU 规格值
MapUtils.findAndThen(skuMap, item.getSkuId(), MapUtils.findAndThen(skuMap, item.getSkuId(),
sku -> item.setSkuProperties(convertList01(sku.getProperties()))); sku -> item.setSkuProperties(convertList01(sku.getProperties())));
}); });

View File

@ -112,10 +112,9 @@ public interface ProductSpuConvert {
} }
default List<ProductSpuDetailRespVO> convertForSpuDetailRespListVO(List<ProductSpuDO> spus, List<ProductSkuDO> skus) { default List<ProductSpuDetailRespVO> convertForSpuDetailRespListVO(List<ProductSpuDO> spus, List<ProductSkuDO> skus) {
List<ProductSpuDetailRespVO> vos = new ArrayList<>(spus.size());
Map<Long, List<ProductSkuDO>> skuMultiMap = convertMultiMap(skus, ProductSkuDO::getSpuId); Map<Long, List<ProductSkuDO>> skuMultiMap = convertMultiMap(skus, ProductSkuDO::getSpuId);
CollectionUtils.convertList(spus, spu -> vos.add(convert03(spu).setSkus(ProductSkuConvert.INSTANCE.convertList(skuMultiMap.get(spu.getId()))))); return CollectionUtils.convertList(spus, spu -> convert03(spu)
return vos; .setSkus(ProductSkuConvert.INSTANCE.convertList(skuMultiMap.get(spu.getId()))));
} }
} }

View File

@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.promotion.api.combination;
import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
import javax.validation.Valid; import javax.validation.Valid;
// TODO @芋艿后面也再撸撸这几个接口
// TODO @芋艿后面也再撸撸这几个接口
/** /**
* 拼团记录 API 接口 * 拼团记录 API 接口
* *
@ -17,17 +17,18 @@ public interface CombinationRecordApi {
* *
* @param reqDTO 请求 DTO * @param reqDTO 请求 DTO
*/ */
void createRecord(@Valid CombinationRecordCreateReqDTO reqDTO); void createCombinationRecord(@Valid CombinationRecordCreateReqDTO reqDTO);
/** /**
* 校验拼团是否成功 * 查询拼团记录是否成功
* *
* @param userId 用户编号 * @param userId 用户编号
* @param orderId 订单编号 * @param orderId 订单编号
* @return 拼团是否成功 * @return 拼团是否成功
*/ */
boolean validateRecordStatusIsSuccess(Long userId, Long orderId); boolean isCombinationRecordSuccess(Long userId, Long orderId);
// TODO @puhui999updateRecordStatus updateRecordStatusAndStartTime 看看后续是不是可以统一掉
/** /**
* 更新开团记录状态 * 更新开团记录状态
* *
@ -35,7 +36,7 @@ public interface CombinationRecordApi {
* @param orderId 订单编号 * @param orderId 订单编号
* @param status 状态值 * @param status 状态值
*/ */
void updateRecordStatus(Long userId, Long orderId, Integer status); void updateCombinationRecordStatus(Long userId, Long orderId, Integer status);
/** /**
* 更新开团记录状态和开始时间 * 更新开团记录状态和开始时间
@ -44,6 +45,6 @@ public interface CombinationRecordApi {
* @param orderId 订单编号 * @param orderId 订单编号
* @param status 状态值 * @param status 状态值
*/ */
void updateRecordStatusAndStartTime(Long userId, Long orderId, Integer status); void updateCombinationRecordStatusAndStartTime(Long userId, Long orderId, Integer status);
} }

View File

@ -5,8 +5,9 @@ import lombok.Data;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
// TODO @芋艿这块要在看看
/** /**
* 拼团记录 Request DTO * 拼团记录的创建 Request DTO
* *
* @author HUIHUI * @author HUIHUI
*/ */

View File

@ -20,23 +20,23 @@ public class CombinationRecordApiImpl implements CombinationRecordApi {
private CombinationRecordService recordService; private CombinationRecordService recordService;
@Override @Override
public void createRecord(CombinationRecordCreateReqDTO reqDTO) { public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) {
recordService.createRecord(reqDTO); recordService.createCombinationRecord(reqDTO);
} }
@Override @Override
public boolean validateRecordStatusIsSuccess(Long userId, Long orderId) { public boolean isCombinationRecordSuccess(Long userId, Long orderId) {
return CombinationRecordStatusEnum.isSuccess(recordService.getRecord(userId, orderId).getStatus()); return CombinationRecordStatusEnum.isSuccess(recordService.getCombinationRecord(userId, orderId).getStatus());
} }
@Override @Override
public void updateRecordStatus(Long userId, Long orderId, Integer status) { public void updateCombinationRecordStatus(Long userId, Long orderId, Integer status) {
recordService.updateRecordStatusByUserIdAndOrderId(userId, orderId, status); recordService.updateCombinationRecordStatusByUserIdAndOrderId(userId, orderId, status);
} }
@Override @Override
public void updateRecordStatusAndStartTime(Long userId, Long orderId, Integer status) { public void updateCombinationRecordStatusAndStartTime(Long userId, Long orderId, Integer status) {
recordService.updateRecordStatusAndStartTimeByUserIdAndOrderId(userId, orderId, status, LocalDateTime.now()); recordService.updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(userId, orderId, status, LocalDateTime.now());
} }
} }

View File

@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.promotion.controller.admin.combination;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
@ -23,9 +22,11 @@ import javax.annotation.Resource;
import javax.validation.Valid; import javax.validation.Valid;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set;
import static cn.hutool.core.collection.CollectionUtil.newArrayList; import static cn.hutool.core.collection.CollectionUtil.newArrayList;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@Tag(name = "管理后台 - 拼团活动") @Tag(name = "管理后台 - 拼团活动")
@RestController @RestController
@ -35,6 +36,7 @@ public class CombinationActivityController {
@Resource @Resource
private CombinationActivityService combinationActivityService; private CombinationActivityService combinationActivityService;
@Resource @Resource
private ProductSpuApi spuApi; private ProductSpuApi spuApi;
@ -68,17 +70,18 @@ public class CombinationActivityController {
@PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')") @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')")
public CommonResult<CombinationActivityRespVO> getCombinationActivity(@RequestParam("id") Long id) { public CommonResult<CombinationActivityRespVO> getCombinationActivity(@RequestParam("id") Long id) {
CombinationActivityDO activity = combinationActivityService.getCombinationActivity(id); CombinationActivityDO activity = combinationActivityService.getCombinationActivity(id);
List<CombinationProductDO> products = combinationActivityService.getProductsByActivityIds(newArrayList(id)); List<CombinationProductDO> products = combinationActivityService.getCombinationProductsByActivityIds(newArrayList(id));
return success(CombinationActivityConvert.INSTANCE.convert(activity, products)); return success(CombinationActivityConvert.INSTANCE.convert(activity, products));
} }
// TODO @puhui999是不是可以删掉貌似没用
@GetMapping("/list") @GetMapping("/list")
@Operation(summary = "获得拼团活动列表") @Operation(summary = "获得拼团活动列表")
@Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048") @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
@PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')") @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')")
public CommonResult<List<CombinationActivityRespVO>> getCombinationActivityList(@RequestParam("ids") Collection<Long> ids) { public CommonResult<List<CombinationActivityRespVO>> getCombinationActivityList(@RequestParam("ids") Collection<Long> ids) {
List<CombinationActivityDO> list = combinationActivityService.getCombinationActivityList(ids); List<CombinationActivityDO> list = combinationActivityService.getCombinationActivityList(ids);
return success(CombinationActivityConvert.INSTANCE.complementList(list)); return success(CombinationActivityConvert.INSTANCE.convertList(list));
} }
@GetMapping("/page") @GetMapping("/page")
@ -86,10 +89,14 @@ public class CombinationActivityController {
@PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')") @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')")
public CommonResult<PageResult<CombinationActivityRespVO>> getCombinationActivityPage( public CommonResult<PageResult<CombinationActivityRespVO>> getCombinationActivityPage(
@Valid CombinationActivityPageReqVO pageVO) { @Valid CombinationActivityPageReqVO pageVO) {
// 查询拼团活动
PageResult<CombinationActivityDO> pageResult = combinationActivityService.getCombinationActivityPage(pageVO); PageResult<CombinationActivityDO> pageResult = combinationActivityService.getCombinationActivityPage(pageVO);
// 拼接数据
Set<Long> activityIds = convertSet(pageResult.getList(), CombinationActivityDO::getId);
Set<Long> spuIds = convertSet(pageResult.getList(), CombinationActivityDO::getSpuId);
return success(CombinationActivityConvert.INSTANCE.convertPage(pageResult, return success(CombinationActivityConvert.INSTANCE.convertPage(pageResult,
combinationActivityService.getProductsByActivityIds(CollectionUtils.convertSet(pageResult.getList(), CombinationActivityDO::getId)), combinationActivityService.getCombinationProductsByActivityIds(activityIds),
spuApi.getSpuList(CollectionUtils.convertSet(pageResult.getList(), CombinationActivityDO::getSpuId)))); spuApi.getSpuList(spuIds)));
} }
} }

View File

@ -79,6 +79,7 @@ public class SeckillActivityController {
return success(SeckillActivityConvert.INSTANCE.convert(seckillActivity, seckillProducts)); return success(SeckillActivityConvert.INSTANCE.convert(seckillActivity, seckillProducts));
} }
// TODO @puhui999是不是可以删掉貌似没用
@GetMapping("/list") @GetMapping("/list")
@Operation(summary = "获得秒杀活动列表") @Operation(summary = "获得秒杀活动列表")
@Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048") @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.promotion.convert.combination; package cn.iocoder.yudao.module.promotion.convert.combination;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
@ -70,7 +71,7 @@ public interface CombinationActivityConvert {
return respVO; return respVO;
} }
List<CombinationActivityRespVO> complementList(List<CombinationActivityDO> list); List<CombinationActivityRespVO> convertList(List<CombinationActivityDO> list);
PageResult<CombinationActivityRespVO> convertPage(PageResult<CombinationActivityDO> page); PageResult<CombinationActivityRespVO> convertPage(PageResult<CombinationActivityDO> page);
@ -80,8 +81,10 @@ public interface CombinationActivityConvert {
Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId); Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
PageResult<CombinationActivityRespVO> pageResult = convertPage(page); PageResult<CombinationActivityRespVO> pageResult = convertPage(page);
pageResult.getList().forEach(item -> { pageResult.getList().forEach(item -> {
MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> item.setSpuName(spu.getName())); MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> {
MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl())); item.setSpuName(spu.getName());
item.setPicUrl(spu.getPicUrl());
});
item.setProducts(convertList2(productList)); item.setProducts(convertList2(productList));
}); });
return pageResult; return pageResult;
@ -100,7 +103,7 @@ public interface CombinationActivityConvert {
}) })
CombinationProductDO convert(CombinationActivityDO activityDO, CombinationProductBaseVO vo); CombinationProductDO convert(CombinationActivityDO activityDO, CombinationProductBaseVO vo);
default List<CombinationProductDO> complementList(List<? extends CombinationProductBaseVO> products, CombinationActivityDO activityDO) { default List<CombinationProductDO> convertList(List<? extends CombinationProductBaseVO> products, CombinationActivityDO activityDO) {
List<CombinationProductDO> list = new ArrayList<>(); List<CombinationProductDO> list = new ArrayList<>();
products.forEach(sku -> { products.forEach(sku -> {
CombinationProductDO productDO = convert(activityDO, sku); CombinationProductDO productDO = convert(activityDO, sku);
@ -110,16 +113,12 @@ public interface CombinationActivityConvert {
return list; return list;
} }
default List<CombinationProductDO> complementList(List<CombinationProductDO> productDOs, List<CombinationProductUpdateReqVO> vos, CombinationActivityDO activityDO) { default List<CombinationProductDO> convertList(List<CombinationProductUpdateReqVO> updateProductVOs,
Map<Long, Long> longMap = convertMap(productDOs, CombinationProductDO::getSkuId, CombinationProductDO::getId); List<CombinationProductDO> products, CombinationActivityDO activity) {
List<CombinationProductDO> list = new ArrayList<>(); Map<Long, Long> productMap = convertMap(products, CombinationProductDO::getSkuId, CombinationProductDO::getId);
vos.forEach(sku -> { return CollectionUtils.convertList(updateProductVOs, updateProductVO -> convert(activity, updateProductVO)
CombinationProductDO productDO = convert(activityDO, sku); .setId(productMap.get(updateProductVO.getSkuId()))
productDO.setId(longMap.get(sku.getSkuId())); .setActivityStatus(activity.getStatus()));
productDO.setActivityStatus(activityDO.getStatus());
list.add(productDO);
});
return list;
} }
CombinationRecordDO convert(CombinationRecordCreateReqDTO reqDTO); CombinationRecordDO convert(CombinationRecordCreateReqDTO reqDTO);

View File

@ -21,6 +21,8 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
/** /**
* 秒杀活动 Convert * 秒杀活动 Convert
* *
@ -37,6 +39,7 @@ public interface SeckillActivityConvert {
SeckillActivityRespVO convert(SeckillActivityDO bean); SeckillActivityRespVO convert(SeckillActivityDO bean);
// TODO @puhui999这个是不是还是 convertList 好点
List<SeckillActivityRespVO> complementList(List<SeckillActivityDO> list); List<SeckillActivityRespVO> complementList(List<SeckillActivityDO> list);
PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page); PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page);
@ -73,7 +76,7 @@ public interface SeckillActivityConvert {
}) })
SeckillProductDO convert(SeckillActivityDO activityDO, SeckillProductBaseVO vo); SeckillProductDO convert(SeckillActivityDO activityDO, SeckillProductBaseVO vo);
default List<SeckillProductDO> complementList(List<? extends SeckillProductBaseVO> products, SeckillActivityDO activityDO) { default List<SeckillProductDO> convertList(List<? extends SeckillProductBaseVO> products, SeckillActivityDO activityDO) {
List<SeckillProductDO> list = new ArrayList<>(); List<SeckillProductDO> list = new ArrayList<>();
products.forEach(sku -> { products.forEach(sku -> {
SeckillProductDO productDO = convert(activityDO, sku); SeckillProductDO productDO = convert(activityDO, sku);
@ -83,16 +86,12 @@ public interface SeckillActivityConvert {
return list; return list;
} }
default List<SeckillProductDO> complementList(List<SeckillProductDO> productDOs, List<SeckillProductUpdateReqVO> vos, SeckillActivityDO activityDO) { default List<SeckillProductDO> convertList(List<SeckillProductUpdateReqVO> updateProductVOs,
Map<Long, Long> longMap = CollectionUtils.convertMap(productDOs, SeckillProductDO::getSkuId, SeckillProductDO::getId); List<SeckillProductDO> products, SeckillActivityDO activity) {
List<SeckillProductDO> list = new ArrayList<>(); Map<Long, Long> productMap = convertMap(products, SeckillProductDO::getSkuId, SeckillProductDO::getId);
vos.forEach(sku -> { return CollectionUtils.convertList(updateProductVOs, updateProductVO -> convert(activity, updateProductVO)
SeckillProductDO productDO = convert(activityDO, sku); .setId(productMap.get(updateProductVO.getSkuId()))
productDO.setId(longMap.get(sku.getSkuId())); .setActivityStatus(activity.getStatus()));
productDO.setActivityStatus(activityDO.getStatus());
list.add(productDO);
});
return list;
} }
List<SeckillProductRespVO> convertList2(List<SeckillProductDO> productDOs); List<SeckillProductRespVO> convertList2(List<SeckillProductDO> productDOs);

View File

@ -12,6 +12,9 @@ import java.time.LocalDateTime;
/** /**
* 拼团记录 DO * 拼团记录 DO
* *
* 1. 用户参与拼团时会创建一条记录
* 2. 团长的拼团记录和参团人的拼团记录通过 {@link #headId} 关联
*
* @author HUIHUI * @author HUIHUI
*/ */
@TableName("promotion_combination_record") @TableName("promotion_combination_record")

View File

@ -15,6 +15,7 @@ import java.util.List;
@Mapper @Mapper
public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO> { public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO> {
// TODO @puhui999selectByUserIdAndOrderId
default CombinationRecordDO selectRecord(Long userId, Long orderId) { default CombinationRecordDO selectRecord(Long userId, Long orderId) {
return selectOne(CombinationRecordDO::getUserId, userId, return selectOne(CombinationRecordDO::getUserId, userId,
CombinationRecordDO::getOrderId, orderId); CombinationRecordDO::getOrderId, orderId);
@ -28,7 +29,8 @@ public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO
* @return 拼团记录 * @return 拼团记录
*/ */
default CombinationRecordDO selectRecordByHeadId(Long headId, Long activityId, Integer status) { default CombinationRecordDO selectRecordByHeadId(Long headId, Long activityId, Integer status) {
return selectOne(CombinationRecordDO::getUserId, headId, CombinationRecordDO::getActivityId, activityId, return selectOne(CombinationRecordDO::getHeadId, headId,
CombinationRecordDO::getActivityId, activityId,
CombinationRecordDO::getStatus, status); CombinationRecordDO::getStatus, status);
} }

View File

@ -70,6 +70,6 @@ public interface CombinationActivityService {
* @param ids 拼团活动 ids * @param ids 拼团活动 ids
* @return 拼团活动的商品列表 * @return 拼团活动的商品列表
*/ */
List<CombinationProductDO> getProductsByActivityIds(Collection<Long> ids); List<CombinationProductDO> getCombinationProductsByActivityIds(Collection<Long> ids);
} }

View File

@ -19,14 +19,14 @@ public interface CombinationRecordService {
* @param orderId 订单编号 * @param orderId 订单编号
* @param status 状态 * @param status 状态
*/ */
void updateRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status); void updateCombinationRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status);
/** /**
* 创建拼团记录 * 创建拼团记录
* *
* @param reqDTO 创建信息 * @param reqDTO 创建信息
*/ */
void createRecord(CombinationRecordCreateReqDTO reqDTO); void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO);
/** /**
* 更新拼团状态和开始时间 * 更新拼团状态和开始时间
@ -36,7 +36,8 @@ public interface CombinationRecordService {
* @param status 状态 * @param status 状态
* @param startTime 开始时间 * @param startTime 开始时间
*/ */
void updateRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId, Integer status, LocalDateTime startTime); void updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId,
Integer status, LocalDateTime startTime);
/** /**
* 获得拼团状态 * 获得拼团状态
@ -45,6 +46,6 @@ public interface CombinationRecordService {
* @param orderId 订单编号 * @param orderId 订单编号
* @return 拼团状态 * @return 拼团状态
*/ */
CombinationRecordDO getRecord(Long userId, Long orderId); CombinationRecordDO getCombinationRecord(Long userId, Long orderId);
} }

View File

@ -37,7 +37,7 @@ import java.util.*;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuExistence; import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuAllExists;
/** /**
* 拼团活动 Service 实现类 * 拼团活动 Service 实现类
@ -66,7 +66,7 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi
// 获取所选 spu下的所有 sku // 获取所选 spu下的所有 sku
List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(createReqVO.getSpuId())); List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(createReqVO.getSpuId()));
// 校验商品 sku 是否存在 // 校验商品 sku 是否存在
validateProductSkuExistence(createReqVO.getProducts(), skus, CombinationProductCreateReqVO::getSkuId); validateProductSkuAllExists(createReqVO.getProducts(), skus, CombinationProductCreateReqVO::getSkuId);
// TODO 艿艿 有个小问题现在有活动时间和限制时长活动时间的结束时间早于设置的限制时间怎么算状态比如 // TODO 艿艿 有个小问题现在有活动时间和限制时长活动时间的结束时间早于设置的限制时间怎么算状态比如
// 活动时间 2023-08-05 15:00:00 - 2023-08-05 15:20:00 限制时长 2小时那么活动时间结束就结束还是加时到满两小时 // 活动时间 2023-08-05 15:00:00 - 2023-08-05 15:20:00 限制时长 2小时那么活动时间结束就结束还是加时到满两小时
@ -80,7 +80,7 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi
activityDO.setStatus(CommonStatusEnum.ENABLE.getStatus()); activityDO.setStatus(CommonStatusEnum.ENABLE.getStatus());
combinationActivityMapper.insert(activityDO); combinationActivityMapper.insert(activityDO);
// 插入商品 // 插入商品
List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.complementList(createReqVO.getProducts(), activityDO); List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), activityDO);
combinationProductMapper.insertBatch(productDOs); combinationProductMapper.insertBatch(productDOs);
// 返回 // 返回
return activityDO.getId(); return activityDO.getId();
@ -118,7 +118,7 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi
// 获取所选 spu下的所有 sku // 获取所选 spu下的所有 sku
List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(updateReqVO.getSpuId())); List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(updateReqVO.getSpuId()));
// 校验商品 sku 是否存在 // 校验商品 sku 是否存在
validateProductSkuExistence(updateReqVO.getProducts(), skus, CombinationProductUpdateReqVO::getSkuId); validateProductSkuAllExists(updateReqVO.getProducts(), skus, CombinationProductUpdateReqVO::getSkuId);
// 更新 // 更新
CombinationActivityDO updateObj = CombinationActivityConvert.INSTANCE.convert(updateReqVO); CombinationActivityDO updateObj = CombinationActivityConvert.INSTANCE.convert(updateReqVO);
@ -140,18 +140,21 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi
// 前端传过来的活动商品 // 前端传过来的活动商品
Set<Long> convertSet1 = CollectionUtils.convertSet(products, CombinationProductUpdateReqVO::getSkuId); Set<Long> convertSet1 = CollectionUtils.convertSet(products, CombinationProductUpdateReqVO::getSkuId);
// 分化数据 // 分化数据
// TODO @芋艿看下这个实现
Map<String, List<CombinationProductDO>> data = CollectionUtils.convertCDUMap(convertSet1, convertSet, mapData -> { Map<String, List<CombinationProductDO>> data = CollectionUtils.convertCDUMap(convertSet1, convertSet, mapData -> {
HashMap<String, List<CombinationProductDO>> cdu = MapUtil.newHashMap(3); HashMap<String, List<CombinationProductDO>> cdu = MapUtil.newHashMap(3);
MapUtils.findAndThen(mapData, "create", list -> { MapUtils.findAndThen(mapData, "create", list -> {
cdu.put("create", CombinationActivityConvert.INSTANCE.complementList(CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj)); cdu.put("create", CombinationActivityConvert.INSTANCE.convertList(CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj));
}); });
MapUtils.findAndThen(mapData, "delete", list -> { MapUtils.findAndThen(mapData, "delete", list -> {
cdu.put("create", CollectionUtils.filterList(combinationProductDOs, item -> list.contains(item.getSkuId()))); cdu.put("create", CollectionUtils.filterList(combinationProductDOs, item -> list.contains(item.getSkuId())));
}); });
MapUtils.findAndThen(mapData, "update", list -> { // TODO @芋艿临时注释避免有问题
cdu.put("update", CombinationActivityConvert.INSTANCE.complementList(combinationProductDOs, // MapUtils.findAndThen(mapData, "update", list -> {
CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj)); // cdu.put("update", CombinationActivityConvert.INSTANCE.convertList(
}); // combinationProductDOs,
// CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj));
// });
return cdu; return cdu;
}); });
@ -199,12 +202,12 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi
} }
@Override @Override
public List<CombinationProductDO> getProductsByActivityIds(Collection<Long> ids) { public List<CombinationProductDO> getCombinationProductsByActivityIds(Collection<Long> ids) {
return combinationProductMapper.selectListByActivityIds(ids); return combinationProductMapper.selectListByActivityIds(ids);
} }
@Override @Override
public void updateRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status) { public void updateCombinationRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status) {
// 校验拼团是否存在 // 校验拼团是否存在
CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId); CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId);
@ -215,7 +218,7 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId, Integer status, LocalDateTime startTime) { public void updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId, Integer status, LocalDateTime startTime) {
CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId); CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId);
// 更新状态 // 更新状态
recordDO.setStatus(status); recordDO.setStatus(status);
@ -247,15 +250,15 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi
} }
@Override @Override
public void createRecord(CombinationRecordCreateReqDTO reqDTO) { public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) {
// 校验拼团活动 // 1.1 校验拼团活动
CombinationActivityDO activity = validateCombinationActivityExists(reqDTO.getActivityId()); CombinationActivityDO activity = validateCombinationActivityExists(reqDTO.getActivityId());
// 需要校验下当前是不是已经参加了该拼团 // 1.2 需要校验下当前是不是已经参加了该拼团
CombinationRecordDO recordDO = recordMapper.selectRecord(reqDTO.getUserId(), reqDTO.getOrderId()); CombinationRecordDO recordDO = recordMapper.selectRecord(reqDTO.getUserId(), reqDTO.getOrderId());
if (recordDO != null) { if (recordDO != null) {
throw exception(COMBINATION_RECORD_EXISTS); throw exception(COMBINATION_RECORD_EXISTS);
} }
// 父拼团是否存在,是否已经满了 // 1.3 父拼团是否存在,是否已经满了
if (reqDTO.getHeadId() != null) { if (reqDTO.getHeadId() != null) {
CombinationRecordDO recordDO1 = recordMapper.selectRecordByHeadId(reqDTO.getHeadId(), reqDTO.getActivityId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); CombinationRecordDO recordDO1 = recordMapper.selectRecordByHeadId(reqDTO.getHeadId(), reqDTO.getActivityId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
if (recordDO1 == null) { if (recordDO1 == null) {
@ -266,9 +269,12 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi
throw exception(COMBINATION_RECORD_USER_FULL); throw exception(COMBINATION_RECORD_USER_FULL);
} }
} }
// TODO @puhui999应该还有一些校验后续补噶例如说一个团自己已经参与进去了不能再参与进去
// 2. 创建拼团记录
CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO); CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO);
if (reqDTO.getHeadId() == null) { if (reqDTO.getHeadId() == null) {
// TODO @puhui999不是自己呀headId 是父团长的 CombinationRecordDO.id
record.setHeadId(reqDTO.getUserId()); record.setHeadId(reqDTO.getUserId());
} }
record.setVirtualGroup(false); record.setVirtualGroup(false);
@ -279,7 +285,7 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi
} }
@Override @Override
public CombinationRecordDO getRecord(Long userId, Long orderId) { public CombinationRecordDO getCombinationRecord(Long userId, Long orderId) {
return validateCombinationRecord(userId, orderId); return validateCombinationRecord(userId, orderId);
} }

View File

@ -34,7 +34,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuExistence; import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuAllExists;
/** /**
* 秒杀活动 Service 实现类 * 秒杀活动 Service 实现类
@ -74,7 +74,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
.setTotalStock(CollectionUtils.getSumValue(createReqVO.getProducts(), SeckillProductCreateReqVO::getStock, Integer::sum)); .setTotalStock(CollectionUtils.getSumValue(createReqVO.getProducts(), SeckillProductCreateReqVO::getStock, Integer::sum));
seckillActivityMapper.insert(activity); seckillActivityMapper.insert(activity);
// 插入商品 // 插入商品
List<SeckillProductDO> products = SeckillActivityConvert.INSTANCE.complementList(createReqVO.getProducts(), activity); List<SeckillProductDO> products = SeckillActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), activity);
seckillProductMapper.insertBatch(products); seckillProductMapper.insertBatch(products);
return activity.getId(); return activity.getId();
} }
@ -121,7 +121,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
// 获取所选 spu下的所有 sku // 获取所选 spu下的所有 sku
List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollUtil.newArrayList(updateReqVO.getSpuId())); List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollUtil.newArrayList(updateReqVO.getSpuId()));
// 校验商品 sku 是否存在 // 校验商品 sku 是否存在
validateProductSkuExistence(updateReqVO.getProducts(), skus, SeckillProductUpdateReqVO::getSkuId); validateProductSkuAllExists(updateReqVO.getProducts(), skus, SeckillProductUpdateReqVO::getSkuId);
// 更新活动 // 更新活动
SeckillActivityDO updateObj = SeckillActivityConvert.INSTANCE.convert(updateReqVO) SeckillActivityDO updateObj = SeckillActivityConvert.INSTANCE.convert(updateReqVO)
@ -150,16 +150,17 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
Map<String, List<SeckillProductDO>> data = CollectionUtils.convertCDUMap(voSkuIds, dbSkuIds, mapData -> { Map<String, List<SeckillProductDO>> data = CollectionUtils.convertCDUMap(voSkuIds, dbSkuIds, mapData -> {
HashMap<String, List<SeckillProductDO>> cdu = MapUtil.newHashMap(3); HashMap<String, List<SeckillProductDO>> cdu = MapUtil.newHashMap(3);
MapUtils.findAndThen(mapData, "create", list -> { MapUtils.findAndThen(mapData, "create", list -> {
cdu.put("create", SeckillActivityConvert.INSTANCE.complementList( cdu.put("create", SeckillActivityConvert.INSTANCE.convertList(
CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj)); CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj));
}); });
MapUtils.findAndThen(mapData, "delete", list -> { MapUtils.findAndThen(mapData, "delete", list -> {
cdu.put("create", CollectionUtils.filterList(seckillProductDOs, item -> list.contains(item.getSkuId()))); cdu.put("create", CollectionUtils.filterList(seckillProductDOs, item -> list.contains(item.getSkuId())));
}); });
MapUtils.findAndThen(mapData, "update", list -> { // TODO @芋艿临时注释
cdu.put("update", SeckillActivityConvert.INSTANCE.complementList(seckillProductDOs, // MapUtils.findAndThen(mapData, "update", list -> {
CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj)); // cdu.put("update", SeckillActivityConvert.INSTANCE.convertList(seckillProductDOs,
}); // CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj));
// });
return cdu; return cdu;
}); });

View File

@ -31,18 +31,20 @@ public class PromotionUtils {
return LocalDateTimeUtils.beforeNow(endTime) ? CommonStatusEnum.DISABLE.getStatus() : CommonStatusEnum.ENABLE.getStatus(); return LocalDateTimeUtils.beforeNow(endTime) ? CommonStatusEnum.DISABLE.getStatus() : CommonStatusEnum.ENABLE.getStatus();
} }
// TODO @puhui999是不是第一个参数是 sku然后是 products这样关联性好点
/** /**
* 校验商品 sku 是否存在 * 校验商品 sku 是否存在
* *
* @param products 需要校验的商品 * @param products 需要校验的商品
* @param skus 数据库中的商品 skus * @param skus 数据库中的商品 skus
* @param func 获取需要校验的商品的 skuId * @param func 获取需要校验的商品的 skuId
*/ */
public static <T> void validateProductSkuExistence(List<T> products, List<ProductSkuRespDTO> skus, Function<T, Long> func) { public static <T> void validateProductSkuAllExists(List<T> products, List<ProductSkuRespDTO> skus, Function<T, Long> func) {
// 校验 sku 个数是否一致 // 校验 sku 个数是否一致
Set<Long> skuIdsSet = CollectionUtils.convertSet(products, func); Set<Long> skuIdsSet = CollectionUtils.convertSet(products, func);
Set<Long> skuIdsSet1 = CollectionUtils.convertSet(skus, ProductSkuRespDTO::getId); Set<Long> skuIdsSet1 = CollectionUtils.convertSet(skus, ProductSkuRespDTO::getId);
// 校验 skuId 是否存在 // 校验 skuId 是否存在
// TODO @puhui999findFirst
List<Long> f = CollectionUtils.filterList(skuIdsSet, s -> !skuIdsSet1.contains(s)); List<Long> f = CollectionUtils.filterList(skuIdsSet, s -> !skuIdsSet1.contains(s));
if (CollUtil.isNotEmpty(f)) { if (CollUtil.isNotEmpty(f)) {
throw exception(SKU_NOT_EXISTS); throw exception(SKU_NOT_EXISTS);

View File

@ -332,6 +332,7 @@ public interface TradeOrderConvert {
@Mapping(target = "avatar", source = "user.avatar"), @Mapping(target = "avatar", source = "user.avatar"),
@Mapping(target = "status", ignore = true) @Mapping(target = "status", ignore = true)
}) })
CombinationRecordCreateReqDTO convert(TradeOrderDO order, TradeOrderItemDO orderItem, AppTradeOrderCreateReqVO createReqVO, MemberUserRespDTO user); CombinationRecordCreateReqDTO convert(TradeOrderDO order, TradeOrderItemDO orderItem,
AppTradeOrderCreateReqVO createReqVO, MemberUserRespDTO user);
} }

View File

@ -27,11 +27,13 @@ public class TradeMessageServiceImpl implements TradeMessageService {
// 1构造消息 // 1构造消息
Map<String, Object> msgMap = new HashMap<>(); Map<String, Object> msgMap = new HashMap<>();
msgMap.put("orderId", reqDTO.getOrderId()); msgMap.put("orderId", reqDTO.getOrderId());
// TODO puhui999应该不是 msg 应该是涉及到的模版参数哈msg 太大了
msgMap.put("msg", reqDTO.getMessage()); msgMap.put("msg", reqDTO.getMessage());
// 2发送站内信 // 2发送站内信
notifyMessageSendApi.sendSingleMessageToMember( notifyMessageSendApi.sendSingleMessageToMember(
new NotifySendSingleToUserReqDTO() new NotifySendSingleToUserReqDTO()
.setUserId(reqDTO.getUserId()) .setUserId(reqDTO.getUserId())
// TODO puhui999短信模版编号枚举起来
.setTemplateCode("order_delivery") .setTemplateCode("order_delivery")
.setTemplateParams(msgMap)); .setTemplateParams(msgMap));
} }

View File

@ -5,6 +5,7 @@ import lombok.Data;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
// TODO @puhui999改成 ReqBO 包名也换了service 我们还是同一用 bo 对象
/** /**
* 订单发货时 Req DTO * 订单发货时 Req DTO
* *

View File

@ -174,7 +174,8 @@ public class TradeOrderServiceImpl implements TradeOrderService {
if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
MemberUserRespDTO user = memberUserApi.getUser(userId); MemberUserRespDTO user = memberUserApi.getUser(userId);
// TODO 拼团一次应该只能选择一种规格的商品 // TODO 拼团一次应该只能选择一种规格的商品
combinationRecordApi.createRecord(TradeOrderConvert.INSTANCE.convert(order, orderItems.get(0), createReqVO, user) // TODO @puhui999应该是前置校验哈然后不应该设置状态而是交给拼团记录那处理
combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(order, orderItems.get(0), createReqVO, user)
.setStatus(CombinationRecordStatusEnum.WAITING.getStatus())); .setStatus(CombinationRecordStatusEnum.WAITING.getStatus()));
} }
// TODO 秒杀扣减库存是下单就扣除还是等待订单支付成功再扣除 // TODO 秒杀扣减库存是下单就扣除还是等待订单支付成功再扣除
@ -311,7 +312,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
// 1拼团活动 // 1拼团活动
if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
// 更新拼团状态 TODO puhui999订单支付失败或订单支付过期删除这条拼团记录 // 更新拼团状态 TODO puhui999订单支付失败或订单支付过期删除这条拼团记录
combinationRecordApi.updateRecordStatusAndStartTime(order.getUserId(), order.getId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); combinationRecordApi.updateCombinationRecordStatusAndStartTime(order.getUserId(), order.getId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
} }
// TODO 芋艿发送订单变化的消息 // TODO 芋艿发送订单变化的消息
@ -376,10 +377,11 @@ public class TradeOrderServiceImpl implements TradeOrderService {
return new KeyValue<>(order, payOrder); return new KeyValue<>(order, payOrder);
} }
// TODO @芋艿后续在 review 下发货逻辑
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void deliveryOrder(Long userId, TradeOrderDeliveryReqVO deliveryReqVO) { public void deliveryOrder(Long userId, TradeOrderDeliveryReqVO deliveryReqVO) {
// 校验并获得交易订单可发货 // 1.1 校验并获得交易订单可发货
TradeOrderDO order = validateOrderDeliverable(deliveryReqVO.getId()); TradeOrderDO order = validateOrderDeliverable(deliveryReqVO.getId());
/* TODO /* TODO
@ -388,35 +390,36 @@ public class TradeOrderServiceImpl implements TradeOrderService {
* 2.如果店铺只支持到店自提那么下单后默认发货不需要物流 * 2.如果店铺只支持到店自提那么下单后默认发货不需要物流
* 3.如果店铺支持 物流-配送-自提 的情况下后台不需要选择配送方式按前端用户选择的配送方式发货即可 * 3.如果店铺支持 物流-配送-自提 的情况下后台不需要选择配送方式按前端用户选择的配送方式发货即可
*/ */
TradeOrderDO tradeOrderDO = new TradeOrderDO(); TradeOrderDO updateOrderObj = new TradeOrderDO();
// 判断发货类型 // 判断发货类型
// 快递发货 // 2.1 快递发货
if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.EXPRESS.getMode())) { if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.EXPRESS.getMode())) {
// 校验快递公司 // 校验快递公司
// TODO @puhui999getDeliveryExpress 直接封装一个校验的会不会好点因为还有开启关闭啥的
DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(deliveryReqVO.getLogisticsId()); DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(deliveryReqVO.getLogisticsId());
if (deliveryExpress == null) { if (deliveryExpress == null) {
throw exception(EXPRESS_NOT_EXISTS); throw exception(EXPRESS_NOT_EXISTS);
} }
tradeOrderDO.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo()); updateOrderObj.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo());
} }
// 用户自提 // 2.2 用户自提
if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.PICK_UP.getMode())) { if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.PICK_UP.getMode())) {
// TODO 校验自提门店是否存在 // TODO 校验自提门店是否存在
// 重置一下确保快递公司和快递单号为空 // 重置一下确保快递公司和快递单号为空
tradeOrderDO.setLogisticsId(null).setLogisticsNo(""); updateOrderObj.setLogisticsId(null).setLogisticsNo("");
} }
// TODO 芋艿如果无需发货需要怎么存储 // 2.3 TODO 芋艿如果无需发货需要怎么存储回复需要把 deliverType 设置为 DeliveryTypeEnum.NULL
if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.NULL.getMode())) { if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.NULL.getMode())) {
// TODO 情况一正常走发货逻辑和用户自提有点像 不同点不需要自提门店只需要用户确认收货 // TODO 情况一正常走发货逻辑和用户自提有点像 不同点不需要自提门店只需要用户确认收货
// TODO 情况二用户下单付款后直接确认收货或等待用户确认收货 // TODO 情况二用户下单付款后直接确认收货或等待用户确认收货
// 重置一下确保快递公司和快递单号为空 // 重置一下确保快递公司和快递单号为空
tradeOrderDO.setLogisticsId(null).setLogisticsNo(""); updateOrderObj.setLogisticsId(null).setLogisticsNo("");
} }
// 更新 TradeOrderDO 状态为已发货等待收货 // 更新 TradeOrderDO 状态为已发货等待收货
tradeOrderDO.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()) updateOrderObj.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus())
.setDeliveryStatus(TradeOrderDeliveryStatusEnum.DELIVERED.getStatus()).setDeliveryTime(LocalDateTime.now()); .setDeliveryStatus(TradeOrderDeliveryStatusEnum.DELIVERED.getStatus()).setDeliveryTime(LocalDateTime.now());
int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), tradeOrderDO); int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), updateOrderObj);
if (updateCount == 0) { if (updateCount == 0) {
throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED);
} }
@ -457,7 +460,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
// 校验订单拼团是否成功 // 校验订单拼团是否成功
// TODO 用户 ID 使用当前登录用户的还是订单保存的 // TODO 用户 ID 使用当前登录用户的还是订单保存的
if (combinationRecordApi.validateRecordStatusIsSuccess(order.getUserId(), order.getId())) { if (combinationRecordApi.isCombinationRecordSuccess(order.getUserId(), order.getId())) {
throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS); throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS);
} }
} }

View File

@ -27,6 +27,7 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -68,7 +69,15 @@ public class MpAccountServiceImpl implements MpAccountService {
// 注意忽略自动多租户因为要全局初始化缓存 // 注意忽略自动多租户因为要全局初始化缓存
TenantUtils.executeIgnore(() -> { TenantUtils.executeIgnore(() -> {
// 第一步查询数据 // 第一步查询数据
List<MpAccountDO> accounts = mpAccountMapper.selectList(); List<MpAccountDO> accounts = Collections.emptyList();
try {
accounts = mpAccountMapper.selectList();
} catch (Throwable ex) {
if (!ex.getMessage().contains("doesn't exist")) {
throw ex;
}
log.error("[微信公众号 yudao-module-mp - 表结构未导入][参考 https://doc.iocoder.cn/mp/build/ 开启]");
}
log.info("[initLocalCacheIfUpdate][缓存公众号账号,数量为:{}]", accounts.size()); log.info("[initLocalCacheIfUpdate][缓存公众号账号,数量为:{}]", accounts.size());
// 第二步构建缓存创建或更新支付 Client // 第二步构建缓存创建或更新支付 Client

View File

@ -27,6 +27,7 @@ import javax.annotation.Resource;
import javax.validation.Validator; import javax.validation.Validator;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -64,7 +65,15 @@ public class PayChannelServiceImpl implements PayChannelService {
// 注意忽略自动多租户因为要全局初始化缓存 // 注意忽略自动多租户因为要全局初始化缓存
TenantUtils.executeIgnore(() -> { TenantUtils.executeIgnore(() -> {
// 第一步查询数据 // 第一步查询数据
List<PayChannelDO> channels = channelMapper.selectList(); List<PayChannelDO> channels = Collections.emptyList();
try {
channels = channelMapper.selectList();
} catch (Throwable ex) {
if (!ex.getMessage().contains("doesn't exist")) {
throw ex;
}
log.error("[支付模块 yudao-module-pay - 表结构未导入][参考 https://doc.iocoder.cn/pay/build/ 开启]");
}
log.info("[initLocalCache][缓存支付渠道,数量为:{}]", channels.size()); log.info("[initLocalCache][缓存支付渠道,数量为:{}]", channels.size());
// 第二步构建缓存创建或更新支付 Client // 第二步构建缓存创建或更新支付 Client

View File

@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO;
import cn.iocoder.yudao.module.system.dal.mysql.mail.MailAccountMapper; import cn.iocoder.yudao.module.system.dal.mysql.mail.MailAccountMapper;
import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants; import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -46,7 +47,7 @@ public class MailAccountServiceImpl implements MailAccountService {
} }
@Override @Override
@Cacheable(value = RedisKeyConstants.MAIL_ACCOUNT, key = "#updateReqVO.id") @CacheEvict(value = RedisKeyConstants.MAIL_ACCOUNT, key = "#updateReqVO.id")
public void updateMailAccount(MailAccountUpdateReqVO updateReqVO) { public void updateMailAccount(MailAccountUpdateReqVO updateReqVO) {
// 校验是否存在 // 校验是否存在
validateMailAccountExists(updateReqVO.getId()); validateMailAccountExists(updateReqVO.getId());
@ -57,7 +58,7 @@ public class MailAccountServiceImpl implements MailAccountService {
} }
@Override @Override
@Cacheable(value = RedisKeyConstants.MAIL_ACCOUNT, key = "#id") @CacheEvict(value = RedisKeyConstants.MAIL_ACCOUNT, key = "#id")
public void deleteMailAccount(Long id) { public void deleteMailAccount(Long id) {
// 校验是否存在账号 // 校验是否存在账号
validateMailAccountExists(id); validateMailAccountExists(id);

View File

@ -52,9 +52,9 @@
<el-input v-model="formData.config.apiV3Key" placeholder="请输入 API V3 密钥" clearable <el-input v-model="formData.config.apiV3Key" placeholder="请输入 API V3 密钥" clearable
:style="{width: '100%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input> :style="{width: '100%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input>
</el-form-item> </el-form-item>
<el-form-item label-width="180px" label="apiclient_key.perm 证书" prop="config.privateKeyContent"> <el-form-item label-width="180px" label="apiclient_key.pem 证书" prop="config.privateKeyContent">
<el-input v-model="formData.config.privateKeyContent" type="textarea" <el-input v-model="formData.config.privateKeyContent" type="textarea"
placeholder="请上传 apiclient_key.perm 证书" placeholder="请上传 apiclient_key.pem 证书"
readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input> readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
</el-form-item> </el-form-item>
<el-form-item label-width="180px" label="" prop="privateKeyContentFile"> <el-form-item label-width="180px" label="" prop="privateKeyContentFile">
@ -132,7 +132,7 @@ export default {
'config.apiVersion': [{ required: true, message: 'API版本不能为空', trigger: 'blur'}], 'config.apiVersion': [{ required: true, message: 'API版本不能为空', trigger: 'blur'}],
'config.mchKey': [{ required: true, message: '请输入商户密钥', trigger: 'blur' }], 'config.mchKey': [{ required: true, message: '请输入商户密钥', trigger: 'blur' }],
'config.keyContent': [{ required: true, message: '请上传 apiclient_cert.p12 证书', trigger: 'blur' }], 'config.keyContent': [{ required: true, message: '请上传 apiclient_cert.p12 证书', trigger: 'blur' }],
'config.privateKeyContent': [{ required: true, message: '请上传 apiclient_key.perm 证书', trigger: 'blur' }], 'config.privateKeyContent': [{ required: true, message: '请上传 apiclient_key.pem 证书', trigger: 'blur' }],
'config.privateCertContent': [{ required: true, message: '请上传 apiclient_cert.perm证 书', trigger: 'blur' }], 'config.privateCertContent': [{ required: true, message: '请上传 apiclient_cert.perm证 书', trigger: 'blur' }],
'config.apiV3Key': [{ required: true, message: '请上传 api V3 密钥值', trigger: 'blur' }], 'config.apiV3Key': [{ required: true, message: '请上传 api V3 密钥值', trigger: 'blur' }],
}, },