mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-26 09:11:52 +08:00
📖 CRM:code review 拼团记录的实现
This commit is contained in:
parent
1b87b8a42f
commit
bbee720710
@ -19,10 +19,9 @@ public interface ProductBrowseHistoryService {
|
|||||||
*
|
*
|
||||||
* @param userId 用户编号
|
* @param userId 用户编号
|
||||||
* @param spuId SPU 编号
|
* @param spuId SPU 编号
|
||||||
* @return 编号
|
|
||||||
*/
|
*/
|
||||||
@Async
|
@Async
|
||||||
Long createBrowseHistory(Long userId, Long spuId);
|
void createBrowseHistory(Long userId, Long spuId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 隐藏用户商品浏览记录
|
* 隐藏用户商品浏览记录
|
||||||
|
@ -26,10 +26,10 @@ public class ProductBrowseHistoryServiceImpl implements ProductBrowseHistoryServ
|
|||||||
private ProductBrowseHistoryMapper browseHistoryMapper;
|
private ProductBrowseHistoryMapper browseHistoryMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long createBrowseHistory(Long userId, Long spuId) {
|
public void createBrowseHistory(Long userId, Long spuId) {
|
||||||
// 用户未登录时不记录
|
// 用户未登录时不记录
|
||||||
if (userId == null) {
|
if (userId == null) {
|
||||||
return null;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 情况一:同一个商品,只保留最新的一条记录
|
// 情况一:同一个商品,只保留最新的一条记录
|
||||||
@ -50,7 +50,6 @@ public class ProductBrowseHistoryServiceImpl implements ProductBrowseHistoryServ
|
|||||||
.setUserId(userId)
|
.setUserId(userId)
|
||||||
.setSpuId(spuId);
|
.setSpuId(spuId);
|
||||||
browseHistoryMapper.insert(browseHistory);
|
browseHistoryMapper.insert(browseHistory);
|
||||||
return browseHistory.getId();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
package cn.iocoder.yudao.module.promotion.controller.app.combination;
|
package cn.iocoder.yudao.module.promotion.controller.app.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.util.object.BeanUtils;
|
||||||
|
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordDetailRespVO;
|
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordDetailRespVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordPageReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordRespVO;
|
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordRespVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordSummaryRespVO;
|
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordSummaryRespVO;
|
||||||
import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
|
import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
|
||||||
@ -13,6 +17,9 @@ import io.swagger.v3.oas.annotations.Operation;
|
|||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.Parameters;
|
import io.swagger.v3.oas.annotations.Parameters;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import jakarta.validation.constraints.Max;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -20,8 +27,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import jakarta.validation.constraints.Max;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@ -73,8 +78,18 @@ public class AppCombinationRecordController {
|
|||||||
@RequestParam(value = "activityId", required = false) Long activityId,
|
@RequestParam(value = "activityId", required = false) Long activityId,
|
||||||
@RequestParam("status") Integer status,
|
@RequestParam("status") Integer status,
|
||||||
@RequestParam(value = "count", defaultValue = "20") @Max(20) Integer count) {
|
@RequestParam(value = "count", defaultValue = "20") @Max(20) Integer count) {
|
||||||
return success(CombinationActivityConvert.INSTANCE.convertList3(
|
List<CombinationRecordDO> list = combinationRecordService.getHeadCombinationRecordList(activityId, status, count);
|
||||||
combinationRecordService.getHeadCombinationRecordList(activityId, status, count)));
|
return success(BeanUtils.toBean(list, AppCombinationRecordRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/page")
|
||||||
|
@Operation(summary = "获得我的拼团记录分页")
|
||||||
|
@PreAuthenticated
|
||||||
|
public CommonResult<PageResult<AppCombinationRecordRespVO>> getCombinationRecordPage(
|
||||||
|
@Valid AppCombinationRecordPageReqVO pageReqVO) {
|
||||||
|
PageResult<CombinationRecordDO> pageResult = combinationRecordService.getCombinationRecordPage(
|
||||||
|
getLoginUserId(), pageReqVO);
|
||||||
|
return success(BeanUtils.toBean(pageResult, AppCombinationRecordRespVO.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/get-detail")
|
@GetMapping("/get-detail")
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
package cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||||
|
import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Schema(description = "用户 App - 拼团记录分页 Request VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class AppCombinationRecordPageReqVO extends PageParam {
|
||||||
|
|
||||||
|
@Schema(description = "拼团状态", example = "1")
|
||||||
|
@InEnum(value = CombinationRecordStatusEnum.class, message = "拼团状态必须是 {value}")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
}
|
@ -33,12 +33,18 @@ public class AppCombinationRecordRespVO {
|
|||||||
@Schema(description = "拼团状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
@Schema(description = "拼团状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
|
||||||
|
private Long orderId;
|
||||||
|
|
||||||
@Schema(description = "商品名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是大黄豆")
|
@Schema(description = "商品名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是大黄豆")
|
||||||
private String spuName;
|
private String spuName;
|
||||||
|
|
||||||
@Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
|
@Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
|
||||||
private String picUrl;
|
private String picUrl;
|
||||||
|
|
||||||
|
@Schema(description = "购买的商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
|
private Integer count;
|
||||||
|
|
||||||
@Schema(description = "拼团金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
@Schema(description = "拼团金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
||||||
private Integer combinationPrice;
|
private Integer combinationPrice;
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
|||||||
@RequestMapping("/promotion/diy-page")
|
@RequestMapping("/promotion/diy-page")
|
||||||
@Validated
|
@Validated
|
||||||
public class AppDiyPageController {
|
public class AppDiyPageController {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private DiyPageService diyPageService;
|
private DiyPageService diyPageService;
|
||||||
|
|
||||||
|
@ -60,7 +60,6 @@ public interface CombinationActivityConvert {
|
|||||||
|
|
||||||
List<CombinationActivityRespVO> convertList(List<CombinationActivityDO> list);
|
List<CombinationActivityRespVO> convertList(List<CombinationActivityDO> list);
|
||||||
|
|
||||||
|
|
||||||
default PageResult<CombinationActivityPageItemRespVO> convertPage(PageResult<CombinationActivityDO> page,
|
default PageResult<CombinationActivityPageItemRespVO> convertPage(PageResult<CombinationActivityDO> page,
|
||||||
List<CombinationProductDO> productList,
|
List<CombinationProductDO> productList,
|
||||||
Map<Long, Integer> groupCountMap,
|
Map<Long, Integer> groupCountMap,
|
||||||
@ -125,7 +124,6 @@ public interface CombinationActivityConvert {
|
|||||||
.setNickname(user.getNickname()).setAvatar(user.getAvatar())
|
.setNickname(user.getNickname()).setAvatar(user.getAvatar())
|
||||||
// 商品信息
|
// 商品信息
|
||||||
.setSpuName(spu.getName()).setPicUrl(sku.getPicUrl());
|
.setSpuName(spu.getName()).setPicUrl(sku.getPicUrl());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<AppCombinationActivityRespVO> convertAppList(List<CombinationActivityDO> list);
|
List<AppCombinationActivityRespVO> convertAppList(List<CombinationActivityDO> list);
|
||||||
|
@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
|||||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordReqPageVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordReqPageVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordPageReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
@ -143,4 +144,11 @@ public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO
|
|||||||
return selectList(CombinationRecordDO::getHeadId, headId);
|
return selectList(CombinationRecordDO::getHeadId, headId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default PageResult<CombinationRecordDO> selectPage(Long userId, AppCombinationRecordPageReqVO pageReqVO) {
|
||||||
|
LambdaQueryWrapperX<CombinationRecordDO> queryWrapper = new LambdaQueryWrapperX<CombinationRecordDO>()
|
||||||
|
.eq(CombinationRecordDO::getUserId, userId)
|
||||||
|
.eqIfPresent(CombinationRecordDO::getStatus, pageReqVO.getStatus());
|
||||||
|
return selectPage(pageReqVO, queryWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|||||||
import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
|
import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
|
||||||
import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationValidateJoinRespDTO;
|
import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationValidateJoinRespDTO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordReqPageVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordReqPageVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordPageReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
|
||||||
@ -163,4 +164,13 @@ public interface CombinationRecordService {
|
|||||||
*/
|
*/
|
||||||
KeyValue<Integer, Integer> expireCombinationRecord();
|
KeyValue<Integer, Integer> expireCombinationRecord();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得拼团记录分页数据
|
||||||
|
*
|
||||||
|
* @param userId 用户编号
|
||||||
|
* @param pageReqVO 分页请求
|
||||||
|
* @return 拼团记录分页数据
|
||||||
|
*/
|
||||||
|
PageResult<CombinationRecordDO> getCombinationRecordPage(Long userId, AppCombinationRecordPageReqVO pageReqVO);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ 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;
|
||||||
import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationValidateJoinRespDTO;
|
import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationValidateJoinRespDTO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordReqPageVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordReqPageVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordPageReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
|
import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
|
||||||
@ -23,14 +24,14 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationR
|
|||||||
import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper;
|
import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper;
|
||||||
import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
|
import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
|
||||||
import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
|
import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
|
||||||
|
import jakarta.annotation.Nullable;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import jakarta.annotation.Nullable;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@ -159,7 +160,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
|
|||||||
// 2.1. 如果是团长需要设置 headId 为 CombinationRecordDO#HEAD_ID_GROUP
|
// 2.1. 如果是团长需要设置 headId 为 CombinationRecordDO#HEAD_ID_GROUP
|
||||||
if (record.getHeadId() == null) {
|
if (record.getHeadId() == null) {
|
||||||
record.setStartTime(LocalDateTime.now())
|
record.setStartTime(LocalDateTime.now())
|
||||||
.setExpireTime(keyValue.getKey().getStartTime().plusHours(keyValue.getKey().getLimitDuration()))
|
.setExpireTime(LocalDateTime.now().plusHours(keyValue.getKey().getLimitDuration()))
|
||||||
.setHeadId(CombinationRecordDO.HEAD_ID_GROUP);
|
.setHeadId(CombinationRecordDO.HEAD_ID_GROUP);
|
||||||
} else {
|
} else {
|
||||||
// 2.2.有团长的情况下需要设置开始时间和过期时间为团长的
|
// 2.2.有团长的情况下需要设置开始时间和过期时间为团长的
|
||||||
@ -408,6 +409,11 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
|
|||||||
return records;
|
return records;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageResult<CombinationRecordDO> getCombinationRecordPage(Long userId, AppCombinationRecordPageReqVO pageReqVO) {
|
||||||
|
return combinationRecordMapper.selectPage(userId, pageReqVO);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得自身的代理对象,解决 AOP 生效问题
|
* 获得自身的代理对象,解决 AOP 生效问题
|
||||||
*
|
*
|
||||||
|
@ -21,18 +21,17 @@ import com.google.common.collect.Maps;
|
|||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import jakarta.validation.Valid;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
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;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||||
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
|
|
||||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||||
|
|
||||||
@Tag(name = "用户 App - 交易订单")
|
@Tag(name = "用户 App - 交易订单")
|
||||||
|
Loading…
Reference in New Issue
Block a user