目录
- 前言
- 思路
- 代码实现
- 实体ThemeActivityGift:spuId由 String类型变为JSONArray
- ThemeActivityGiftServiceImpl改造
- handleYxGiftByOperation:保存的是严选的生日品
- checkSpuIds:校验SPU有效性
- checkSpuIdExist:校验单个spuId是否存在
- checkSkuIds:校验SKUs的有效性
- checkSkuIdExist:校验单个SKU ID是否存在
- checkNoRepeatValue:判断是否有重复的值
前言
业务需求如下:
内心觉得这个需求写的真“棒”,我花了好长时间才理解清楚,这需求的写法对刚加入进来项目的新人一点都不友好。唉,而且这个需求它写出来都有错(改善点中应该是SPUID而不是SKUID),所以啊工作中还是要多交流,不然呵呵 ,被带偏绝对跑不了,增加开发难度,唉
思路
首先:理解业务需求:
现状:上架网易严选生日品的功能中SPU名称不支持输入多个值,SPU名称和SKU列表是一对多关系。需加入多SPU对多SKU的场景。
重点:从一个开发者角度考虑的场景,这个思路清晰了可帮助我们自测代码,减少BUG。
我觉得场景可以分以下四种情况:
第一种:输入正确的SPU和SKU
1、单SPU+单SKU | 通过 |
---|---|
2、单SPU+多SKU | 通过 |
3、多SPU+多SKU | 通过 |
第二种:输入错误的SPU和SKU
1、单SPU+单SKU | 不通过 |
---|---|
2、单SPU+多SKU | 不通过 |
3、多SPU+多SKU | 不通过 |
第三种:添加是正确的但不是网易严选的SPU 不通过
第四种:重复插入的SPU 不通过
重点考虑多SPU+多SKU 的校验场景,我的想法为:验证SKU的模块中,只要所有的sku去遍历spu,只要校验通过其中一个spu,就算校验成功。
举例如下:
商品A和B的SPU和SKU如下所示:
A | SPU:10018002 SKU :10019005 |
---|---|
B | SPU:1273186784766128130 SKU:1273186784774516738,1273186784778711042 |
现在在前端输入多SPU+多SKU,如下所示:
名称 | SPU列表和SKU列表 |
---|---|
A+B | SPU:10018002,1273186784766128130 SKU : 10019005,1273186784774516738,1273186784778711042 |
那么校验SKU时,只要SKU中的值和其中一个SPU校验通过,就算成功。
代码实现
实体ThemeActivityGift:spuId由 String类型变为JSONArray
/**
* 对接网易严选的spuName
*/
private String spuName;
/**
* 对接网易严选的spuId(外键)
*/
@TableField(typeHandler = JsonArrayTypeHandler.class, jdbcType = JdbcType.VARCHAR)
private JSONArray spuIdArray;
/**
* 对接网易严选的skuIdArray(外键)
*/
@TableField(typeHandler = JsonArrayTypeHandler.class, jdbcType = JdbcType.VARCHAR)
private JSONArray skuIdArray;
ThemeActivityGiftServiceImpl改造
礼品新增功能访问的是如下方法:
/**
* @Description: 主题活动礼品新增
*/
@Override
public R saveGift(ThemeActivityGiftDTO themeActivityGiftDto) {
//虚拟商品的积分值不能为空,请检查
if (ObjectUtil.isNotNull(themeActivityGiftDto.getIsVirtual()) && themeActivityGiftDto.getIsVirtual().equals(WelfareBlessingVirtualEnum.IS_VIRTUAL.getValue())) {
if (ObjectUtil.isNull(themeActivityGiftDto.getPointsValue())) {
return R.failed("虚拟商品的积分值不能为空,请检查");
}
}
//对9级的逻辑进行礼品价格层面的限制。
//保存的是网易品
if (StrUtil.isAllNotBlank(themeActivityGiftDto.getSpuIds(), themeActivityGiftDto.getSpuName(), themeActivityGiftDto.getSkuIds())) {
Pair<Boolean, String> handleResult = handleYxGiftByOperation(themeActivityGiftDto, WelfareConst.OPERATION_CREATE);
if (handleResult.getKey().equals(Boolean.FALSE)) {
return R.failed(handleResult.getValue());
}
return R.ok();
}
ThemeActivityGift themeActivityGift = BeanUtil.copyProperties(themeActivityGiftDto, ThemeActivityGift.class);
//保存的是主题活动
if (themeActivityGift.getType().equals(ThemeActivityGiftTypeEnum.DEFAULT.getValue())) {
if (StrUtil.hasBlank(themeActivityGiftDto.getSpec(), themeActivityGiftDto.getSpecValueString())) {
return R.failed("请输入对应的规格以及规格值!");
}
String spec = themeActivityGiftDto.getSpec();
String specValues = themeActivityGiftDto.getSpecValueString();
themeActivityGift.setSpec(spec);
themeActivityGift.setSpecValueArray(JSONUtil.parseArray(StrUtil.splitToArray(specValues, ThemeActivityConst.COMMA)));
}
themeActivityGift.setSpuName(null);
themeActivityGift.setSpuIdArray(null);
themeActivityGift.setSkuIdArray(null);
return R.ok(baseMapper.insert(themeActivityGift));
}
要对其中网易品实现方法handleYxGiftByOperation
进行改造,重点改造checkSpuIds()和checkSkuIds()
方法
handleYxGiftByOperation:保存的是严选的生日品
/**
* @Description: 保存的是严选的生日品
*/
private Pair<Boolean, String> handleYxGiftByOperation(ThemeActivityGiftDTO themeActivityGiftDto, int operation) {
String spuIds = themeActivityGiftDto.getSpuIds();
String skuIds = themeActivityGiftDto.getSkuIds();
Pair<Boolean, String> checkSpuIdFlag = checkSpuIds(themeActivityGiftDto, spuIds);
Pair<Boolean, String> checkSkuIdFlag = checkSkuIds(spuIds, skuIds);
if (Boolean.FALSE.equals(checkSpuIdFlag.getKey())) {
return new Pair<>(Boolean.FALSE, checkSpuIdFlag.getValue());
}
if (Boolean.FALSE.equals(checkSkuIdFlag.getKey())) {
return new Pair<>(Boolean.FALSE, checkSkuIdFlag.getValue());
}
ThemeActivityGift themeActivityGift = BeanUtil.copyProperties(themeActivityGiftDto, ThemeActivityGift.class);
themeActivityGift.setSpuIdArray(JSONUtil.parseArray(StrUtil.splitToArray(spuIds, ThemeActivityConst.COMMA)));
themeActivityGift.setSkuIdArray(JSONUtil.parseArray(StrUtil.splitToArray(skuIds, ThemeActivityConst.COMMA)));
if (WelfareConst.OPERATION_CREATE == operation) {
baseMapper.insert(themeActivityGift);
} else {
baseMapper.updateById(themeActivityGift);
}
return new Pair<>(Boolean.TRUE, null);
}
checkSpuIds:校验SPU有效性
/**
* @Description: 校验SPU有效性
*/
private Pair<Boolean, String> checkSpuIds(ThemeActivityGiftDTO themeActivityGiftDto, String spuIdArrays) {
//兼容新建礼品时,没有giftId
String giftId = ObjectUtil.isNotNull(themeActivityGiftDto.getId()) ? themeActivityGiftDto.getId() : "";
if (StrUtil.isBlank(spuIdArrays)) {
return new Pair<>(Boolean.FALSE, "spuIds不能为空,请检查");
}
//把string转化为数据库存储的数组形式来进行新增重复数据校验,如10018002,1273186784766128130 转化为["10018002,1273186784766128130"]
spuIdArrays=spuIdArrays.replace(",", "\",\"");
spuIdArrays="[\""+spuIdArrays+"\"]";
//在更新礼品记录时,校验重复,不能与自身记录进行判断
Wrapper<ThemeActivityGift> queryWrapper;
if (StrUtil.isBlank(giftId)) {
queryWrapper = Wrappers.<ThemeActivityGift>lambdaQuery()
.eq(ThemeActivityGift::getSpuIdArray,spuIdArrays);
} else {
queryWrapper = Wrappers.<ThemeActivityGift>lambdaQuery()
.eq(ThemeActivityGift::getSpuIdArray, spuIdArrays)
.ne(ThemeActivityGift::getId, giftId);
}
ThemeActivityGift themeActivityGift = this.baseMapper.selectOne(queryWrapper);
if (ObjectUtil.isNotNull(themeActivityGift)) {
return new Pair<>(Boolean.FALSE, "该SpuId已与现有的礼品绑定,请检查");
}
//重复校验完后进行复原
spuIdArrays=spuIdArrays.replace("\",\"",",");
spuIdArrays=spuIdArrays.replace("[\"", "");
spuIdArrays=spuIdArrays.replace("\"]", "");
//多个SPU
if (spuIdArrays.contains(ThemeActivityConst.COMMA)) {
String[] spuIdArray = StrUtil.splitToArray(spuIdArrays, ThemeActivityConst.COMMA);
if (!checkNoRepeatValue(spuIdArray)) {
return new Pair<>(Boolean.FALSE, "检测到重复的spuId,请检查");
}
for (String spuId : spuIdArray) {
if (!checkSpuIdExist(spuId)) {
return new Pair<>(Boolean.FALSE, "校验单个SPU ID是否存在失败,spuId =" + spuId);
}
}
return new Pair<>(Boolean.TRUE, null);
}
//单个SPU
if (!checkSpuIdExist(spuIdArrays)) {
return new Pair<>(Boolean.FALSE, "校验单个SPU ID是否存在失败, spuIdArrays =" + spuIdArrays);
}
return new Pair<>(Boolean.TRUE, null);
}
checkSpuIdExist:校验单个spuId是否存在
/**
* @Description: 校验单个spuId是否存在
*/
private boolean checkSpuIdExist(String spuId) {
log.info("checkSpuIdExist spuId= 【{}】", spuId);
GoodsSpu goodsSpu = goodsSpuService.getById(spuId);
if (ObjectUtil.isNull(goodsSpu)) {
log.info("获取GoodSpu异常,请检查");
return Boolean.FALSE;
}
if (!ProductChannelEnum.YANXUAN.getValue().equals(goodsSpu.getChannel())) {
log.info("维护的SpuId并非网易严选的品,请检查");
return Boolean.FALSE;
}
return Boolean.TRUE;
}
checkSkuIds:校验SKUs的有效性
/**
* @Description: 校验SKUs的有效性
*/
private Pair<Boolean, String> checkSkuIds(String spuIds, String skuIdArrays) {
if (StrUtil.isBlank(skuIdArrays)) {
return new Pair<>(Boolean.FALSE, " SKU ID数组不能为空,请检查");
}
//多个SKU
if (skuIdArrays.contains(ThemeActivityConst.COMMA)) {
String[] skuIdArray = StrUtil.splitToArray(skuIdArrays, ThemeActivityConst.COMMA);
if (!checkNoRepeatValue(skuIdArray)) {
return new Pair<>(Boolean.FALSE, "检测到重复的skuId,请检查");
}
for (String skuId : skuIdArray) {
if (!checkSkuIdExist(spuIds, skuId)) {
return new Pair<>(Boolean.FALSE, "获取GoodSku异常,校验单个SKU ID是否存在,skuId =" + skuId);
}
}
return new Pair<>(Boolean.TRUE, null);
}
//单个SKU
if (!checkSkuIdExist(spuIds, skuIdArrays)) {
return new Pair<>(Boolean.FALSE, "获取GoodSku异常,校验单个SKU ID是否存在, skuIdArrays =" + skuIdArrays);
}
return new Pair<>(Boolean.TRUE, null);
}
checkSkuIdExist:校验单个SKU ID是否存在
/**
* @Description: 校验单个SKU ID是否存在
*/
private boolean checkSkuIdExist(String spuIds, String skuId) {
log.info("checkSkuIdExist spuIds= 【{}】,skuId= 【{}】", spuIds, skuId);
GoodsSku goodsSku = goodsSkuService.getById(skuId);
if (ObjectUtil.isNull(goodsSku)) {
log.error("checkSkuIdExist fail. goodsSku是空的!请检查!");
return Boolean.FALSE;
}
//多SPU
if (spuIds.contains(ThemeActivityConst.COMMA)) {
String[] spuIdArray = StrUtil.splitToArray(spuIds, ThemeActivityConst.COMMA);
boolean checkSpuFlag=false;
//检查多spu+多spu的情况,只要spu和其中一个sku对应上,就检验成功
for (String spuId : spuIdArray) {
if (StrUtil.equals(spuId, goodsSku.getSpuId())) {
checkSpuFlag=true;
}
}
if (checkSpuFlag) {
return Boolean.TRUE;
}else{
log.error("checkSkuIdExist fail. 添加的skuId必须是属于这个spu商品的!请检查!");
return Boolean.FALSE;
}
} else{
//单SPU
if (!StrUtil.equals(spuIds, goodsSku.getSpuId())) {
log.error("checkSkuIdExist fail. 添加的skuId必须是属于这个spu商品的!请检查!");
return Boolean.FALSE;
}
}
return Boolean.TRUE;
}
checkNoRepeatValue:判断是否有重复的值
/**
* @Description: 判断是否有重复的值
*/
public static boolean checkNoRepeatValue(String[] array) {
HashSet<String> hashSet = new HashSet<>();
for (int i = 0; i < array.length; i++) {
hashSet.add(array[i]);
}
if (hashSet.size() == array.length) {
return Boolean.TRUE;
}
return Boolean.FALSE;
}