【Xiaoxi】Optimize the function of syncing NetEase strict selection of birthday products to support multi-SPU to multi-SKU relationship

foreword

The business requirements are as follows:
insert image description here
In my heart, I feel that this requirement is really "great". It took me a long time to understand it clearly. The way this requirement is written is not friendly to newcomers who have just joined the project. Alas, and this requirement is written wrong (the improvement point should be SPUID instead of SKUID), so we still need to communicate more at work, otherwise, hehe, he will definitely not be able to escape if he is biased, which will increase the difficulty of development, alas

train of thought

First: understand the business needs :
current situation: the SPU name does not support multiple values ​​in the function of listing Netease Yanxuan birthday products , and the SPU name and SKU list are in a one-to-many relationship. The multi-SPU to multi-SKU scenario needs to be added .

Key point: From a developer's point of view , this clear idea can help us self-test the code and reduce BUG.

I think the scenarios can be divided into the following four situations:
The first one : input the correct SPU and SKU

1. Single SPU+Single SKU pass
2. Single SPU+Multiple SKUs pass
3. Multi-SPU+multi-SKU pass

Type 2 : Enter wrong SPU and SKU

1. Single SPU+Single SKU Fail
2. Single SPU+Multiple SKUs Fail
3. Multi-SPU+multi-SKU Fail

The third type : the addition is correct but the SPU not strictly selected by Netease fails

The fourth type : repeated insertion of SPU does not pass

Focusing on the multi-SPU+multi-SKU verification scenario, my idea is: in the verification SKU module, as long as all skus go through the spu, as long as the verification passes one of the spu, the verification is successful.

An example is as follows:
the SPU and SKU of products A and B are as follows:

A SPU:10018002 SKU:10019005
B SPU :1273186784766128130 SKU :1273186784774516738,1273186784778711042

Now enter multi-SPU+multi-SKU on the front end, as shown below:

name SPU list and SKU list
A+B SPU :10018002,1273186784766128130 SKU : 10019005,1273186784774516738,1273186784778711042

Then when verifying the SKU, as long as the value in the SKU and one of the SPUs pass the verification, it is considered successful.

Code

Entity ThemeActivityGift: spuId changed from String type to 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 transformation

The new function of gift access is as follows:

    /**
     * @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));
    }

handleYxGiftByOperationIt is necessary to transform the implementation method of Netease products , focusing on the transformation checkSpuIds()和checkSkuIds()method

handleYxGiftByOperation: Save carefully selected birthday gifts

    /**
     * @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: Check the validity of 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: Check whether a single spuId exists

	/**
	 * @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: Check the validity of 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: Check whether a single SKU ID exists

       /**
     * @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: Determine whether there are repeated values

    /**
     * @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;
    }

Guess you like

Origin blog.csdn.net/someday____/article/details/128496282