目录
- 前言
- 思路
- 代码实现
- 实体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: 主题活动礼品新增*/@Overridepublic 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) {//兼容新建礼品时,没有giftIdString 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("\"]", "");//多个SPUif (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);}//单个SPUif (!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数组不能为空,请检查");}//多个SKUif (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);}//单个SKUif (!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;}//多SPUif (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{//单SPUif (!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;}