JavaShop项目总结

@TOCJavaShop项目总结

功能

总结一下,在JavaShop中所做的功能修改。

商铺后台

促销管理

商铺后台的活动时间,在活动开始后,也可以进行更改。

  1. 满减满赠
    com/enation/app/javashop/seller/api/promotion/FullDiscountSellerController.java
	@PutMapping(value = "/{id}")
	@ApiOperation(value	= "修改满优惠活动", response = FullDiscountDO.class)
	@ApiImplicitParams({
     
		 @ApiImplicitParam(name	= "id",	value =	"主键",	required = true, dataType = "int",	paramType =	"path")
	})
	public	FullDiscountVO edit(@Valid @RequestBody FullDiscountVO fullDiscountVO, @PathVariable Integer id) {
     

		fullDiscountVO.setFdId(id);
		this.verifyFullDiscountParam(fullDiscountVO,1);
		this.fullDiscountManager.verifyAuth(id);
		this.fullDiscountManager.edit(fullDiscountVO,id);

		return	fullDiscountVO;
	}

在调用修改方法之前,使用this.verifyFullDiscountParam(fullDiscountVO,1);
对满优惠活动的参数信息进行验证;使用this.fullDiscountManager.verifyAuth(id);
来验证操作权限,判断用户是否越权操作。

	@Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {
     RuntimeException.class, Exception.class, ServiceException.class, NoPermissionException.class})
    public FullDiscountVO edit(FullDiscountVO fullDiscountVO, Integer id) {
     
        //验证活动时间,同一时间只能有一个活动生效
        this.verifyTime(fullDiscountVO.getStartTime(), fullDiscountVO.getEndTime(), PromotionTypeEnum.FULL_DISCOUNT, id);

        List<PromotionGoodsDTO> goodsDTOList = new ArrayList<>();
        //是否是全部商品参与
        if (fullDiscountVO.getRangeType() == 1) {
     
            PromotionGoodsDTO goodsDTO = new PromotionGoodsDTO();
            goodsDTO.setGoodsId(-1);
            goodsDTO.setGoodsName("全部商品");
            goodsDTO.setThumbnail("");
            goodsDTOList.add(goodsDTO);
            fullDiscountVO.setGoodsList(goodsDTOList);
        }
        this.verifyRule(fullDiscountVO.getGoodsList());

        // 获取当前登录的店铺ID
        Seller seller = UserContext.getSeller();
        Integer sellerId = seller.getSellerId();
        fullDiscountVO.setSellerId(sellerId);

        FullDiscountDO fullDiscountDO = new FullDiscountDO();
        BeanUtils.copyProperties(fullDiscountVO, fullDiscountDO);

        this.daoSupport.update(fullDiscountDO, id);

        //删除之前的活动与商品的对照关系
        PromotionDetailDTO detailDTO = new PromotionDetailDTO();
        detailDTO.setStartTime(fullDiscountVO.getStartTime());
        detailDTO.setEndTime(fullDiscountVO.getEndTime());
        detailDTO.setActivityId(fullDiscountVO.getFdId());
        detailDTO.setPromotionType(PromotionTypeEnum.FULL_DISCOUNT.name());
        detailDTO.setTitle(fullDiscountVO.getTitle());

        //将活动商品入库
        this.promotionGoodsManager.edit(fullDiscountVO.getGoodsList(), detailDTO);
        cache.put(PromotionCacheKeys.getFullDiscountKey(fullDiscountVO.getFdId()), fullDiscountDO);

        return fullDiscountVO;
    }

this.verifyTime(fullDiscountVO.getStartTime(), fullDiscountVO.getEndTime(), PromotionTypeEnum.FULL_DISCOUNT, id);
这里验证活动时间,同一时间只能有一个活动生效。
this.verifyRule(fullDiscountVO.getGoodsList());
判断商品集合是否为空,检测活动与活动之间的规则冲突。
cache.put(PromotionCacheKeys.getFullDiscountKey(fullDiscountVO.getFdId()), fullDiscountDO);
写入缓存。

  1. 单品立减
    com/enation/app/javashop/seller/api/promotion/MinusSellerController.java
	@PutMapping(value = "/{id}")
	@ApiOperation(value	= "修改单品立减", response = MinusVO.class)
	@ApiImplicitParams({
     
		 @ApiImplicitParam(name	= "id",	value =	"主键",	required = true, dataType = "int",	paramType =	"path")
	})
	public	MinusVO edit(@Valid @RequestBody MinusVO minus, @PathVariable Integer id) {
     

		this.minusManager.verifyAuth(id);
		PromotionValid.paramValid(minus.getStartTime(),minus.getEndTime(),minus.getRangeType(),minus.getGoodsList(),1);
		minus.setMinusId(id);
		this.minusManager.edit(minus,id);

		return	minus;
	}

同满减满赠。

  1. 第二件半价
    com/enation/app/javashop/seller/api/promotion/HalfPriceSellerController.java
	@PutMapping(value = "/{id}")
	@ApiOperation(value	= "修改第二件半价", response = HalfPriceDO.class)
	@ApiImplicitParams({
     
		 @ApiImplicitParam(name	= "id",	value =	"主键",	required = true, dataType = "int",	paramType =	"path")
	})
	public	HalfPriceVO edit(@Valid @RequestBody HalfPriceVO halfPrice, @PathVariable Integer id) {
     
		PromotionValid.paramValid(halfPrice.getStartTime(),halfPrice.getEndTime(),
				halfPrice.getRangeType(),halfPrice.getGoodsList(),1);

		halfPrice.setHpId(id);
		this.halfPriceManager.verifyAuth(id);
		this.halfPriceManager.edit(halfPrice,id);

		return	halfPrice;
	}

同上。

  1. 拼团管理
    com/enation/app/javashop/seller/api/promotion/PintuanSellerController.java
	@ApiOperation(value = "添加活动")
    @PostMapping
    public Pintuan add(@Valid Pintuan pintuan) {
     
        return this.pintuanManager.add(pintuan);
    }
    
    @ApiOperation(value = "修改活动")
    @ApiImplicitParams({
     
            @ApiImplicitParam(name = "id", value = "主键", required = true, dataType = "int", paramType = "path")
    })
    @PutMapping(value = "/{id}")
    public Pintuan edit(@Valid Pintuan activeDO, @PathVariable Integer id) {
     
        this.pintuanManager.edit(activeDO, id);
        return activeDO;
    }

先看添加活动,

	@Override
    @Transactional(value = "tradeTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Pintuan add(Pintuan pintuan) {
     

        this.verifyParam(pintuan.getStartTime(), pintuan.getEndTime());
        pintuan.setStatus(PromotionStatusEnum.WAIT.name());
        pintuan.setSellerName(UserContext.getSeller().getSellerName());
        pintuan.setCreateTime(DateUtil.getDateline());
        pintuan.setSellerId(UserContext.getSeller().getSellerId());
        //可操作状态为nothing,代表活动不可以执行任何操作
        pintuan.setOptionStatus(PintuanOptionEnum.NOTHING.name());
        this.tradeDaoSupport.insert(pintuan);
        Integer pintuanId = this.tradeDaoSupport.getLastId("es_pintuan");
        pintuan.setPromotionId(pintuanId);

        //创建活动 启用延时任务
        PintuanChangeMsg pintuanChangeMsg = new PintuanChangeMsg();
        pintuanChangeMsg.setPintuanId(pintuan.getPromotionId());
        pintuanChangeMsg.setOptionType(1);
        timeTrigger.add(TimeExecute.PINTUAN_EXECUTER, pintuanChangeMsg, pintuan.getStartTime(), TRIGGER_PREFIX + pintuan.getPromotionId());
        pintuan.setPromotionId(this.tradeDaoSupport.getLastId("es_pintuan"));
        return pintuan;
    }

this.verifyParam(pintuan.getStartTime(), pintuan.getEndTime());
判断开始时间是否小于结束时间。
timeTrigger.add()
创建活动时,使用延时任务。rabbitmq实现

	@Override
    public void add(String executerName, Object param, Long triggerTime, String uniqueKey) {
     

        if (StringUtil.isEmpty(uniqueKey)) {
     
            uniqueKey = StringUtil.getRandStr(10);
        }
        //标识任务需要执行
        cache.put(RabbitmqTriggerUtil.generate(executerName, triggerTime, uniqueKey), 1);

        TimeTriggerMsg timeTriggerMsg = new TimeTriggerMsg(executerName, param, triggerTime, uniqueKey);
        if (logger.isDebugEnabled()) {
     
            logger.debug("定时执行在【" + DateUtil.toString(triggerTime, "yyyy-MM-dd HH:mm:ss") + "】,消费【" + param.toString() + "】");
        }
        rabbitTemplate.convertAndSend(TimeTriggerConfig.DELAYED_EXCHANGE_XDELAY, TimeTriggerConfig.DELAY_ROUTING_KEY_XDELAY, timeTriggerMsg, message -> {
     

            Long current = DateUtil.getDateline();
            //如果执行的延时任务应该是在现在日期之前执行的,那么补救一下,要求系统一秒钟后执行
            if (triggerTime < current) {
     
                message.getMessageProperties().setDelay(1000);
            } else {
     
                Long time = (triggerTime - current) * 1000 + 5000;
                message.getMessageProperties().setHeader("x-delay", time);
            }
            if (logger.isDebugEnabled()) {
     
                logger.debug("还有【" + message.getMessageProperties().getExpiration() + "】执行任务");
            }

            return message;
        });
    }

修改活动时,分为活动开始之前修改和活动进行中修改

	@Override
    @Transactional(value = "tradeTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Pintuan edit(Pintuan pintuan, Integer id) {
     
        //获取拼团活动
        Pintuan oldPintaun = this.getModel(id);
        //校验拼团是否可以被操作

        this.verifyParam(pintuan.getStartTime(), pintuan.getEndTime());
        this.tradeDaoSupport.update(pintuan, id);
        //如果在活动开始之前修改
        if(pintuan.getStatus().equals(PromotionStatusEnum.WAIT.name())) {
     
            PintuanChangeMsg pintuanChangeMsg = new PintuanChangeMsg();
            pintuanChangeMsg.setPintuanId(pintuan.getPromotionId());
            pintuanChangeMsg.setOptionType(1);
            timeTrigger.edit(TimeExecute.PINTUAN_EXECUTER, pintuanChangeMsg, oldPintaun.getStartTime(), pintuan.getStartTime(), TRIGGER_PREFIX + id);
        } else {
     
            //活动中,先删除活动的旧关闭任务
            timeTrigger.delete(TimeExecute.PINTUAN_EXECUTER,oldPintaun.getEndTime(),"{TIME_TRIGGER}_"  + id);
            //添加活动的新关闭任务
            PintuanChangeMsg pintuanChangeMsg = new PintuanChangeMsg();
            pintuanChangeMsg.setPintuanId(id);
            pintuanChangeMsg.setOptionType(0);
            timeTrigger.add(TimeExecute.PINTUAN_EXECUTER, pintuanChangeMsg, pintuan.getEndTime(), "{TIME_TRIGGER}_" + id);
        }
        return pintuan;
    }

因为在活动开始之后,会在执行开始活动之后,再向MQ中设置一个关闭活动的延时任务。所以,在活动开始之前修改,只需要修改活动时间以及MQ的开始活动延时任务即可;在活动进行中修改,需要先删除旧的关闭活动的延时任务,再向MQ中设置一个新的关闭活动的延时任务。

	@Override
    public void execute(Object object) {
     
        PintuanChangeMsg pintuanChangeMsg = (PintuanChangeMsg) object;

        //如果是要开启活动

        if (pintuanChangeMsg.getOptionType() == 1) {
     
            Pintuan pintuan = pintuanManager.getModel(pintuanChangeMsg.getPintuanId());
            if (PromotionStatusEnum.WAIT.name().equals(pintuan.getStatus()) ||
                    (PromotionStatusEnum.END.name().equals(pintuan.getStatus()) && PintuanOptionEnum.CAN_OPEN.name().equals(pintuan.getOptionStatus()))) {
     
                pintuanManager.openPromotion(pintuanChangeMsg.getPintuanId());
                //开启活动后,立马设置一个关闭的流程
                pintuanChangeMsg.setOptionType(0);
                timeTrigger.add(TimeExecute.PINTUAN_EXECUTER, pintuanChangeMsg, pintuan.getEndTime(), "{TIME_TRIGGER}_" + pintuan.getPromotionId());
                if (logger.isDebugEnabled()) {
     
                    this.logger.debug("活动[" + pintuan.getPromotionName() + "]开始,id=[" + pintuan.getPromotionId() + "]");
                }
            }
        } else {
     
            //拼团活动结束
            Pintuan pintuan = pintuanManager.getModel(pintuanChangeMsg.getPintuanId());
            if (pintuan.getStatus().equals(PromotionStatusEnum.UNDERWAY.name())) {
     
                pintuanManager.closePromotion(pintuanChangeMsg.getPintuanId());
            }
            if (logger.isDebugEnabled()) {
     
                this.logger.debug("活动[" + pintuan.getPromotionName() + "]结束,id=[" + pintuan.getPromotionId() + "]");
            }
        }

设置管理

PC端信任登录,登录配置功能
com/enation/app/javashop/seller/api/shopconnect/ShopConnectSettingController.java
点击信任登录,查询列表时,先查询该店铺是否配置过,如果没有,先对配置信息进行添加操作,再返回列表。

会员管理

会员回收站,列表展示、搜索、操作(恢复)。
com/enation/app/javashop/seller/api/member/MemberSellerController.java

	@ApiOperation(value = "查询列表", response = Member.class)
    @GetMapping(value = "/list")
    public Page list(@Valid MemberQueryParam memberQueryParam, @ApiIgnore Integer pageNo,
                     @ApiIgnore Integer pageSize) {
     
        memberQueryParam.setPageNo(pageNo);
        memberQueryParam.setPageSize(pageSize);
        return this.memberManager.list(memberQueryParam);
    }
    
    @PostMapping(value = "/recovery/{id}")
    @ApiOperation(value = "恢复会员")
    @ApiImplicitParams({
     
            @ApiImplicitParam(name = "id", value = "要恢复的会员主键", required = true, dataType = "int", paramType = "path")
    })
    public Member recovery(@PathVariable Integer id) {
     
        Member member = memberManager.getModel(id);
        if (member == null) {
     
            throw new ResourceNotFoundException("当前会员不存在");
        }
        if (member.getDisabled().equals(-1)) {
     
            member.setDisabled(0);
            member.setDisabledTime(null);
            this.memberManager.edit(member, id);
        }
        return member;
    }

前台

小唛店订单

com/enation/app/javashop/buyer/api/trade/OrderBuyerController.java
在列表查询时,修改了SQL语句,关联出订单涉及的商品名称,用于关键字查询。在不改动原有查询条件的基础上,新增了一个关键字字段。
在按标签查询(tag页)时,新增了一个用于小唛店已完成列表查询的case,
XIAO_COMPLETE
原因是小唛店在点击确认收货之后,订单就要显示在已完成列表,而原有易旺铺程序在确认收货之后的订单状态为ROG(已收货)。
还复制了一套商铺后台用到的订单列表查询方法,将原有的已完成(COMPLETE)查询条件做了变更,能查询出COMPLETE和ROG状态的订单,原因是商铺后天列表查询的条件传值即为COMPLETE,不能做出修改。

搜索

商户前台商品搜索和店铺搜索功能,让其只能查询出易旺铺的商品和店铺。

实现商品搜索的前提,在添加商品时,按照店铺id查询其店铺类别,并将店铺类别插入到商品表中。com/enation/app/javashop/seller/api/goods/GoodsSellerController.java

	@ApiOperation(value = "添加商品", response = GoodsDO.class)
	@ApiImplicitParam(name = "goods", value = "商品信息", required = true, dataType = "GoodsDTO", paramType = "body")
	@PostMapping
	public GoodsDO add(@ApiIgnore @Valid @RequestBody GoodsDTO goods) {
     
		GoodsDO  goodsDO = this.goodsManager.add(goods);
		return goodsDO;
	}
  1. 商品
    com/enation/app/javashop/buyer/api/goods/GoodsSearchBuyerController.java
    商品搜索在构建查询条件的方法中,加入店铺类别的搜索条件,并设置默认值为1(易旺铺)。
		// 店铺类别(易旺铺)
        boolQueryBuilder.must(QueryBuilders.termQuery("shopTypeId", "1"));

在商品索引实现的实现类中,找到封装成内存需要格式数据的方法,在索引中加入店铺类别,就可以在查询时,实现只查询易旺铺商品。
2. 店铺
com/enation/app/javashop/buyer/api/shop/ShopBuyerController.java

	@ApiOperation(value = "查询店铺列表", response = ShopListVO.class)
    @GetMapping("/list")
    @ApiImplicitParams({
     
            @ApiImplicitParam(name = "page_no", value = "页码", required = true, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "page_size", value = "分页数", required = true, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "name", value = "店铺名称", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "order", value = "按好评率排序", required = false, dataType = "String", paramType = "query")
    })
    public Page list(@ApiIgnore @NotNull(message = "页码不能为空") Integer pageNo, @ApiIgnore @NotNull(message = "每页数量不能为空") Integer pageSize, String name, String order) {
     
        ShopParamsVO shopParams = new ShopParamsVO();
        shopParams.setPageNo(pageNo);
        shopParams.setPageSize(pageSize);
        shopParams.setShopName(name);
        shopParams.setOrder(order);
        return shopManager.listShopBasicInfo(shopParams);
    }

在店铺列表查询的SQL语句中,加入店铺类别字段并默认值为1(易旺铺),即可实现功能。

平台

店铺菜单权限

完善平台后台的店铺菜单权限功能,实现店铺菜单权限的添加修改和删除功能。
com/enation/app/javashop/manager/api/shop/ShopMenuAuthController.java
店铺菜单权限,实现的功能是对一类店铺进行菜单权限的配置,关联到店铺类别表。所以,在添加功能时,先对店铺类别进行了添加操作,然后再将菜单权限信息入库。

	@Override
    public ShopMenuAuthVO add(ShopMenuAuthVO shopMenuAuthVO) {
     

        //添加店铺类别
        ShopType shopType = new ShopType();
        shopType.setTypeName(shopMenuAuthVO.getShopTypeName());
        this.memberDaoSupport.insert(shopType);
        //角色信息入库
        ShopMenuAuthDO shopMenuAuthDO = new ShopMenuAuthDO();
        shopMenuAuthDO.setAuthDescribe(shopMenuAuthVO.getShopTypeName() + "菜单");
        shopMenuAuthDO.setShopTypeId(memberDaoSupport.getLastId("es_shop_type"));
        shopMenuAuthDO.setAuthIds(JsonUtil.objectToJson(queryShopMenuList()));
        this.memberDaoSupport.insert(shopMenuAuthDO);
        shopMenuAuthVO.setId(memberDaoSupport.getLastId("es_shop_menu_auth"));
        return shopMenuAuthVO;
    }

其中用到了 queryShopMenuList() 方法对所有的店铺菜单信息进行了查询。这么做的原因是,如果不在添加时,将所有店铺菜单信息转换成Json串格式插入到数据库中,那么就不能进行修改操作,前台会出现异常。

	/**
     * 查询店铺菜单信息集合
     *
     * @param
     * @return List
     */
    private List<ShopMenus> queryShopMenuList() {
     
        String sql = "SELECT id,parent_id,title,identifier,auth_regular,delete_flag,path,grade FROM es_shop_menu WHERE delete_flag = 0";
        //店铺菜单信息集合
        List<ShopMenu> rootShopMenuList = this.memberDaoSupport.queryForList(sql, ShopMenu.class);
        //要返回的结果店铺菜单信息集合
        List<ShopMenus> shopMenusList = new ArrayList<>();
        //先找到所有的一级菜单
        if(rootShopMenuList != null && rootShopMenuList.size() > 0) {
     
            //遍历所有菜单集合
            for(int i = 0 ; i < rootShopMenuList.size() ; i++) {
     
                //一级菜单没有父id
                if(rootShopMenuList.get(i).getParentId() == 0) {
     
                    ShopMenus shopMenus = new ShopMenus();
                    shopMenus.setId(rootShopMenuList.get(i).getId());
                    shopMenus.setTitle(rootShopMenuList.get(i).getTitle());
                    shopMenus.setIdentifier(rootShopMenuList.get(i).getIdentifier());
                    shopMenus.setChecked(false);
                    shopMenus.setAuthRegular(rootShopMenuList.get(i).getAuthRegular());
                    //将菜单加入集合
                    shopMenusList.add(shopMenus);
                }
            }
            //为一级菜单设置子菜单
            if(shopMenusList != null && shopMenusList.size() > 0) {
     
                for(ShopMenus shopMenus : shopMenusList) {
     
                    shopMenus.setChildren(getMenuChild(shopMenus.getId(), rootShopMenuList));
                }
            }
        }
        return shopMenusList;
    }

    /**
     * 递归查找子菜单
     *
     * @param menuId,rootShopMenuList
     * @return List
     */
    private List<ShopMenus> getMenuChild(Integer menuId, List<ShopMenu> rootShopMenuList) {
     
        //子菜单
        List<ShopMenus> childList = new ArrayList<ShopMenus>();
        for(ShopMenu shopMenu : rootShopMenuList) {
     
            if(shopMenu.getParentId() == menuId) {
     
                ShopMenus shopMenus = new ShopMenus();
                shopMenus.setId(shopMenu.getId());
                shopMenus.setTitle(shopMenu.getTitle());
                shopMenus.setIdentifier(shopMenu.getIdentifier());
                shopMenus.setChecked(false);
                shopMenus.setAuthRegular(shopMenu.getAuthRegular());
                //将子菜单加入集合
                childList.add(shopMenus);
            }
        }
        // 把子菜单的子菜单再循环一遍
        if(childList.size() > 0) {
     
            for(ShopMenus shopMenus : childList) {
     
                //递归
                shopMenus.setChildren(getMenuChild(shopMenus.getId(), rootShopMenuList));
            }
        }
        //递归退出条件
        if(childList.size() == 0) {
     
            return null;
        }
        return childList;
    }

你可能感兴趣的:(java)