refactor travel
This commit is contained in:
@ -0,0 +1,97 @@
|
||||
package com.imyeyu.api.modules.journal.controller;
|
||||
|
||||
import com.imyeyu.api.modules.common.service.AttachmentService;
|
||||
import com.imyeyu.api.modules.journal.entity.Travel;
|
||||
import com.imyeyu.api.modules.journal.service.TravelService;
|
||||
import com.imyeyu.spring.annotation.AOPLog;
|
||||
import com.imyeyu.spring.annotation.RequestRateLimit;
|
||||
import com.imyeyu.spring.annotation.RequestSingleParam;
|
||||
import com.imyeyu.spring.bean.Page;
|
||||
import com.imyeyu.spring.bean.PageResult;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 旅行计划接口
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2025-12-12 14:50
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/journal/travel")
|
||||
public class TravelController {
|
||||
|
||||
private final TravelService service;
|
||||
private final AttachmentService attachmentService;
|
||||
|
||||
/**
|
||||
* 创建旅行计划
|
||||
*
|
||||
* @param travel 旅行计划
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@PostMapping("/create")
|
||||
public void create(@RequestBody @Valid Travel travel) {
|
||||
service.create(travel);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新旅行计划
|
||||
*
|
||||
* @param travel 旅行计划
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@PostMapping("/update")
|
||||
public void update(@RequestBody @Valid Travel travel) {
|
||||
service.update(travel);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除旅行计划(级联删除关联地点和附件)
|
||||
*
|
||||
* @param id 旅行 ID
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@PostMapping("/delete")
|
||||
public void delete(@RequestSingleParam Long id) {
|
||||
service.delete(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询旅行计划详情
|
||||
*
|
||||
* @param id 旅行 ID
|
||||
* @return 旅行计划
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@GetMapping("/{id}")
|
||||
public Travel detail(@PathVariable Long id) {
|
||||
return service.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 旅行计划列表
|
||||
*
|
||||
* @param page 分页参数
|
||||
* @return 旅行列表
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@PostMapping("/list")
|
||||
public PageResult<Travel> list(@RequestBody Page<Travel> page) {
|
||||
return service.page(page);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,136 @@
|
||||
package com.imyeyu.api.modules.journal.controller;
|
||||
|
||||
import com.imyeyu.api.bean.PreviewPage;
|
||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||
import com.imyeyu.api.modules.common.service.AttachmentService;
|
||||
import com.imyeyu.api.modules.journal.entity.TravelLocation;
|
||||
import com.imyeyu.api.modules.journal.service.TravelLocationService;
|
||||
import com.imyeyu.spring.annotation.AOPLog;
|
||||
import com.imyeyu.spring.annotation.RequestRateLimit;
|
||||
import com.imyeyu.spring.annotation.RequestSingleParam;
|
||||
import com.imyeyu.spring.bean.Page;
|
||||
import com.imyeyu.spring.bean.PageResult;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 旅行地点接口
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2025-12-12 14:50
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/journal/travel/location")
|
||||
public class TravelLocationController {
|
||||
|
||||
private final AttachmentService attachmentService;
|
||||
private final TravelLocationService service;
|
||||
|
||||
/**
|
||||
* 创建旅行地点
|
||||
*
|
||||
* @param location 旅行地点
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@PostMapping("/create")
|
||||
public void create(@RequestBody @Valid TravelLocation location) {
|
||||
service.create(location);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新旅行地点
|
||||
*
|
||||
* @param location 旅行地点
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@PostMapping("/update")
|
||||
public void update(@RequestBody @Valid TravelLocation location) {
|
||||
service.update(location);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除旅行地点(级联删除附件)
|
||||
*
|
||||
* @param id 地点 ID
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@PostMapping("/delete")
|
||||
public void delete(@RequestSingleParam Long id) {
|
||||
service.delete(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询旅行地点详情
|
||||
*
|
||||
* @param id 地点 ID
|
||||
* @return 旅行地点
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@GetMapping("/{id}")
|
||||
public TravelLocation detail(@PathVariable Long id) {
|
||||
TravelLocation location = service.get(id);
|
||||
location.setItems(attachmentService.listByBizId(Attachment.BizType.JOURNAL_TRAVEL, location.getId()));
|
||||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* 旅行地点列表
|
||||
*
|
||||
* @param page 分页参数
|
||||
* @return 地点列表
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@PostMapping("/list")
|
||||
public PageResult<TravelLocation> list(@RequestBody PreviewPage<TravelLocation> page) {
|
||||
PageResult<TravelLocation> result = service.page(page);
|
||||
for (TravelLocation location : result.getList()) {
|
||||
Page<Attachment> attachPage = new Page<>();
|
||||
{
|
||||
Attachment example = new Attachment();
|
||||
example.setBizType(Attachment.BizType.JOURNAL_TRAVEL);
|
||||
example.setBizId(location.getId());
|
||||
attachPage.setEqualsExample(example);
|
||||
}
|
||||
attachPage.setIndex(0);
|
||||
attachPage.setSize(1); // 列表接口只允许预览
|
||||
location.setItems(attachmentService.page(attachPage).getList());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@PostMapping("/list/ids")
|
||||
public List<TravelLocation> listByIds(@RequestBody Long[] ids) {
|
||||
List<TravelLocation> locationList = service.listByIds(ids);
|
||||
for (TravelLocation location : locationList) {
|
||||
Page<Attachment> attachPage = new Page<>();
|
||||
{
|
||||
Attachment example = new Attachment();
|
||||
example.setBizType(Attachment.BizType.JOURNAL_TRAVEL);
|
||||
example.setBizId(location.getId());
|
||||
attachPage.setEqualsExample(example);
|
||||
}
|
||||
attachPage.setIndex(0);
|
||||
attachPage.setSize(Long.MAX_VALUE);
|
||||
location.setItems(attachmentService.page(attachPage).getList());
|
||||
}
|
||||
return locationList;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,83 @@
|
||||
package com.imyeyu.api.modules.journal.entity;
|
||||
|
||||
import com.imyeyu.spring.annotation.table.PageIgnore;
|
||||
import com.imyeyu.spring.entity.Entity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 旅行计划
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2025-12-12 14:30
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class Travel extends Entity {
|
||||
|
||||
/**
|
||||
* 交通类型
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2025-12-12 14:30
|
||||
*/
|
||||
public enum TransportationType {
|
||||
|
||||
/** 飞机 */
|
||||
PLANE,
|
||||
|
||||
/** 火车 */
|
||||
TRAIN,
|
||||
|
||||
/** 汽车 */
|
||||
CAR,
|
||||
|
||||
/** 轮船 */
|
||||
SHIP,
|
||||
|
||||
/** 自驾 */
|
||||
SELF_DRIVING,
|
||||
|
||||
/** 其他 */
|
||||
OTHER
|
||||
}
|
||||
|
||||
/**
|
||||
* 旅行状态
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2025-12-12 14:30
|
||||
*/
|
||||
public enum Status {
|
||||
|
||||
/** 计划中 */
|
||||
PLANNING,
|
||||
|
||||
/** 进行中 */
|
||||
ONGOING,
|
||||
|
||||
/** 已完成 */
|
||||
COMPLETED,
|
||||
}
|
||||
|
||||
/** 交通类型 */
|
||||
@PageIgnore
|
||||
private TransportationType transportationType;
|
||||
|
||||
/** 标题 */
|
||||
private String title;
|
||||
|
||||
/** 内容 */
|
||||
@PageIgnore
|
||||
private String content;
|
||||
|
||||
/** 出行时间 */
|
||||
private Long travelAt;
|
||||
|
||||
/** 天数 */
|
||||
@PageIgnore
|
||||
private Integer days;
|
||||
|
||||
/** 状态 */
|
||||
private Status status;
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
package com.imyeyu.api.modules.journal.entity;
|
||||
|
||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||
import com.imyeyu.spring.annotation.table.Transient;
|
||||
import com.imyeyu.spring.entity.Entity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 旅行地点
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2025-12-12 14:30
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class TravelLocation extends Entity {
|
||||
|
||||
/**
|
||||
* 地点类型
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2025-12-12 14:30
|
||||
*/
|
||||
public enum Type {
|
||||
|
||||
/** 景点 */
|
||||
ATTRACTION,
|
||||
|
||||
/** 酒店 */
|
||||
HOTEL,
|
||||
|
||||
/** 餐厅 */
|
||||
RESTAURANT,
|
||||
|
||||
/** 交通站点 */
|
||||
TRANSPORT,
|
||||
|
||||
/** 购物 */
|
||||
SHOPPING,
|
||||
|
||||
/** 其他 */
|
||||
OTHER
|
||||
}
|
||||
|
||||
/** 旅行计划 ID */
|
||||
private Long travelId;
|
||||
|
||||
/** 类型 */
|
||||
private Type type;
|
||||
|
||||
/** 标题 */
|
||||
private String title;
|
||||
|
||||
/** 说明 */
|
||||
private String description;
|
||||
|
||||
/** 纬度 */
|
||||
private Double lat;
|
||||
|
||||
/** 经度 */
|
||||
private Double lng;
|
||||
|
||||
/** 位置 */
|
||||
private String location;
|
||||
|
||||
/** 费用 */
|
||||
private BigDecimal amount;
|
||||
|
||||
/** true 为需要身份证 */
|
||||
private Boolean requireIdCard;
|
||||
|
||||
/** 必要评分 */
|
||||
private Integer score;
|
||||
|
||||
@Transient
|
||||
private Long[] attachmentIds;
|
||||
|
||||
@Transient
|
||||
private String[] tempFileIds;
|
||||
|
||||
@Transient
|
||||
private List<Attachment> items;
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.imyeyu.api.modules.journal.mapper;
|
||||
|
||||
import com.imyeyu.api.modules.journal.entity.TravelLocation;
|
||||
import com.imyeyu.spring.mapper.BaseMapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 旅行地点 Mapper
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2025-12-12 14:35
|
||||
*/
|
||||
public interface TravelLocationMapper extends BaseMapper<TravelLocation, Long> {
|
||||
|
||||
List<TravelLocation> listByIds(Long[] ids);
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.imyeyu.api.modules.journal.mapper;
|
||||
|
||||
import com.imyeyu.api.modules.journal.entity.Travel;
|
||||
import com.imyeyu.spring.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 旅行计划 Mapper
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2025-12-12 14:35
|
||||
*/
|
||||
public interface TravelMapper extends BaseMapper<Travel, Long> {
|
||||
|
||||
/**
|
||||
* 根据 ID 列表查询
|
||||
*
|
||||
* @param ids ID 列表
|
||||
* @return 旅行列表
|
||||
*/
|
||||
List<Travel> listByIds(@Param("ids") Long[] ids);
|
||||
|
||||
/**
|
||||
* 根据状态查询
|
||||
*
|
||||
* @param status 状态
|
||||
* @return 旅行列表
|
||||
*/
|
||||
List<Travel> listByStatus(@Param("status") Travel.Status status);
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package com.imyeyu.api.modules.journal.service;
|
||||
|
||||
import com.imyeyu.api.modules.journal.entity.TravelLocation;
|
||||
import com.imyeyu.java.bean.timi.TimiException;
|
||||
import com.imyeyu.spring.service.BaseService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 旅行地点服务
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2025-12-12 14:40
|
||||
*/
|
||||
public interface TravelLocationService extends BaseService<TravelLocation, Long> {
|
||||
|
||||
List<TravelLocation> listByIds(Long... ids);
|
||||
|
||||
/**
|
||||
* 根据旅行 ID 删除所有地点
|
||||
*
|
||||
* @param travelId 旅行 ID
|
||||
* @throws TimiException 服务异常
|
||||
*/
|
||||
void deleteByTravelId(Long travelId) throws TimiException;
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package com.imyeyu.api.modules.journal.service;
|
||||
|
||||
import com.imyeyu.api.modules.journal.entity.Travel;
|
||||
import com.imyeyu.spring.service.BaseService;
|
||||
|
||||
/**
|
||||
* 旅行计划服务
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2025-12-12 14:40
|
||||
*/
|
||||
public interface TravelService extends BaseService<Travel, Long> {
|
||||
}
|
||||
@ -0,0 +1,111 @@
|
||||
package com.imyeyu.api.modules.journal.service.implement;
|
||||
|
||||
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
||||
import com.imyeyu.api.modules.common.bean.MediaAttach;
|
||||
import com.imyeyu.api.modules.common.bean.TempFileMetaData;
|
||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||
import com.imyeyu.api.modules.common.service.AttachmentService;
|
||||
import com.imyeyu.api.modules.common.service.TempFileService;
|
||||
import com.imyeyu.api.modules.journal.entity.TravelLocation;
|
||||
import com.imyeyu.api.modules.journal.mapper.TravelLocationMapper;
|
||||
import com.imyeyu.api.modules.journal.service.TravelLocationService;
|
||||
import com.imyeyu.java.TimiJava;
|
||||
import com.imyeyu.java.bean.timi.TimiException;
|
||||
import com.imyeyu.spring.mapper.BaseMapper;
|
||||
import com.imyeyu.spring.service.AbstractEntityService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 旅行地点服务实现
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2025-12-12 14:45
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TravelLocationServiceImplement extends AbstractEntityService<TravelLocation, Long> implements TravelLocationService {
|
||||
|
||||
private final TempFileService tempFileService;
|
||||
private final AttachmentService attachmentService;
|
||||
|
||||
private final TravelLocationMapper mapper;
|
||||
|
||||
@Override
|
||||
protected BaseMapper<TravelLocation, Long> mapper() {
|
||||
return mapper;
|
||||
}
|
||||
|
||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||
@Override
|
||||
public void create(TravelLocation travelLocation) {
|
||||
super.create(travelLocation);
|
||||
for (String tempFileId : travelLocation.getTempFileIds()) {
|
||||
TempFileMetaData metadata = tempFileService.metadata(tempFileId);
|
||||
|
||||
Attachment attach = new Attachment();
|
||||
attach.setName(metadata.getOriginalName());
|
||||
attach.setBizType(Attachment.BizType.JOURNAL_TRAVEL);
|
||||
attach.setBizId(travelLocation.getId());
|
||||
attach.setInputStream(tempFileService.getInputStream(tempFileId));
|
||||
attachmentService.createMedia(attach);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||
@Override
|
||||
public void update(TravelLocation travelLocation) {
|
||||
super.update(travelLocation);
|
||||
// 删除
|
||||
Set<Long> dbAttachSet = attachmentService.listByBizId(Attachment.BizType.JOURNAL_TRAVEL, travelLocation.getId(), MediaAttach.Type.THUMB)
|
||||
.stream()
|
||||
.map(Attachment::getId)
|
||||
.collect(Collectors.toSet());
|
||||
Set<Long> retainIds = Set.of(TimiJava.firstNotEmpty(travelLocation.getAttachmentIds(), new Long[0]));
|
||||
dbAttachSet.removeAll(retainIds);
|
||||
for (Long removeId : dbAttachSet) {
|
||||
attachmentService.deleteMedia(removeId);
|
||||
}
|
||||
// 新增
|
||||
for (String tempFileId : TimiJava.firstNotNull(travelLocation.getTempFileIds(), new String[0])) {
|
||||
TempFileMetaData metadata = tempFileService.metadata(tempFileId);
|
||||
|
||||
Attachment attach = new Attachment();
|
||||
attach.setName(metadata.getOriginalName());
|
||||
attach.setBizType(Attachment.BizType.JOURNAL_TRAVEL);
|
||||
attach.setBizId(travelLocation.getId());
|
||||
attach.setInputStream(tempFileService.getInputStream(tempFileId));
|
||||
attachmentService.createMedia(attach);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||
@Override
|
||||
public void delete(Long id) {
|
||||
super.delete(id);
|
||||
attachmentService.deleteByBizId(Attachment.BizType.JOURNAL_TRAVEL, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TravelLocation> listByIds(Long... ids) {
|
||||
return mapper.listByIds(ids);
|
||||
}
|
||||
|
||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||
@Override
|
||||
public void deleteByTravelId(Long travelId) throws TimiException {
|
||||
TravelLocation example = new TravelLocation();
|
||||
example.setTravelId(travelId);
|
||||
List<TravelLocation> locationList = mapper.selectAllByExample(example);
|
||||
for (TravelLocation location : locationList) {
|
||||
delete(location.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package com.imyeyu.api.modules.journal.service.implement;
|
||||
|
||||
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
||||
import com.imyeyu.api.modules.journal.entity.Travel;
|
||||
import com.imyeyu.api.modules.journal.mapper.TravelMapper;
|
||||
import com.imyeyu.api.modules.journal.service.TravelLocationService;
|
||||
import com.imyeyu.api.modules.journal.service.TravelService;
|
||||
import com.imyeyu.spring.mapper.BaseMapper;
|
||||
import com.imyeyu.spring.service.AbstractEntityService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* 旅行计划服务实现
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2025-12-12 14:45
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TravelServiceImplement extends AbstractEntityService<Travel, Long> implements TravelService {
|
||||
|
||||
private final TravelMapper mapper;
|
||||
private final TravelLocationService travelLocationService;
|
||||
|
||||
@Override
|
||||
protected BaseMapper<Travel, Long> mapper() {
|
||||
return mapper;
|
||||
}
|
||||
|
||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||
@Override
|
||||
public void delete(Long id) {
|
||||
super.delete(id);
|
||||
travelLocationService.deleteByTravelId(id);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user