1. 管理后台,增加租户管理

2. 修复大量因为租户报错的单元测试
This commit is contained in:
YunaiV
2021-12-14 22:39:43 +08:00
parent a582a6e726
commit 098c5b4723
45 changed files with 1240 additions and 178 deletions

View File

@@ -1,29 +1,106 @@
package cn.iocoder.yudao.adminserver.modules.system.controller.tenant;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.*;
import cn.iocoder.yudao.adminserver.modules.system.convert.tenant.SysTenantConvert;
import cn.iocoder.yudao.adminserver.modules.system.service.tenant.SysTenantService;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.Objects;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Api(tags = "租户")
@RestController
@RequestMapping("/system/tenant")
public class SysTenantController {
@Resource
private SysTenantService tenantService;
@GetMapping("/get-id-by-name")
@ApiOperation(value = "使用租户名,获得租户编号", notes = "登录界面,根据用户的租户名,获得租户编号")
@ApiImplicitParam(name = "name", value = "租户名", required = true, example = "芋道源码", dataTypeClass = Long.class)
public CommonResult<Long> getTenantIdByName(@RequestParam("name") String name) {
if (Objects.equals("芋道源码", name)) {
return CommonResult.success(1L);
}
return CommonResult.success(null);
SysTenantDO tenantDO = tenantService.getTenantByName(name);
return success(tenantDO != null ? tenantDO.getId() : null);
}
@PostMapping("/create")
@ApiOperation("创建租户")
@PreAuthorize("@ss.hasPermission('system:tenant:create')")
public CommonResult<Long> createTenant(@Valid @RequestBody SysTenantCreateReqVO createReqVO) {
return success(tenantService.createTenant(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新租户")
@PreAuthorize("@ss.hasPermission('system:tenant:update')")
public CommonResult<Boolean> updateTenant(@Valid @RequestBody SysTenantUpdateReqVO updateReqVO) {
tenantService.updateTenant(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除租户")
@ApiImplicitParam(name = "id", value = "编号", required = true)
@PreAuthorize("@ss.hasPermission('system:tenant:delete')")
public CommonResult<Boolean> deleteTenant(@RequestParam("id") Long id) {
tenantService.deleteTenant(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得租户")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('system:tenant:query')")
public CommonResult<SysTenantRespVO> getTenant(@RequestParam("id") Long id) {
SysTenantDO tenant = tenantService.getTenant(id);
return success(SysTenantConvert.INSTANCE.convert(tenant));
}
@GetMapping("/list")
@ApiOperation("获得租户列表")
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
@PreAuthorize("@ss.hasPermission('system:tenant:query')")
public CommonResult<List<SysTenantRespVO>> getTenantList(@RequestParam("ids") Collection<Long> ids) {
List<SysTenantDO> list = tenantService.getTenantList(ids);
return success(SysTenantConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@ApiOperation("获得租户分页")
@PreAuthorize("@ss.hasPermission('system:tenant:query')")
public CommonResult<PageResult<SysTenantRespVO>> getTenantPage(@Valid SysTenantPageReqVO pageVO) {
PageResult<SysTenantDO> pageResult = tenantService.getTenantPage(pageVO);
return success(SysTenantConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@ApiOperation("导出租户 Excel")
@PreAuthorize("@ss.hasPermission('system:tenant:export')")
@OperateLog(type = EXPORT)
public void exportTenantExcel(@Valid SysTenantExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<SysTenantDO> list = tenantService.getTenantList(exportReqVO);
// 导出 Excel
List<SysTenantExcelVO> datas = SysTenantConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "租户.xls", "数据", SysTenantExcelVO.class, datas);
}
}

View File

@@ -0,0 +1,30 @@
package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
/**
* 租户 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class SysTenantBaseVO {
@ApiModelProperty(value = "租户名", required = true, example = "芋道")
@NotNull(message = "租户名不能为空")
private String name;
@ApiModelProperty(value = "联系人", required = true, example = "芋艿")
@NotNull(message = "联系人不能为空")
private String contactName;
@ApiModelProperty(value = "联系手机", example = "15601691300")
private String contactMobile;
@ApiModelProperty(value = "租户状态0正常 1停用", required = true, example = "1")
@NotNull(message = "租户状态0正常 1停用不能为空")
private Integer status;
}

View File

@@ -0,0 +1,14 @@
package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("租户创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SysTenantCreateReqVO extends SysTenantBaseVO {
}

View File

@@ -0,0 +1,39 @@
package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import com.alibaba.excel.annotation.ExcelProperty;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
/**
* 租户 Excel VO
*
* @author 芋道源码
*/
@Data
public class SysTenantExcelVO {
@ExcelProperty("租户编号")
private Long id;
@ExcelProperty("租户名")
private String name;
@ExcelProperty("联系人")
private String contactName;
@ExcelProperty("联系手机")
private String contactMobile;
@ExcelProperty(value = "租户状态0正常 1停用", converter = DictConvert.class)
@DictFormat("sys_common_status") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
private Integer status;
@ExcelProperty("创建时间")
private Date createTime;
}

View File

@@ -0,0 +1,36 @@
package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel(value = "租户 Excel 导出 Request VO", description = "参数和 SysTenantPageReqVO 是一致的")
@Data
public class SysTenantExportReqVO {
@ApiModelProperty(value = "租户名", example = "芋道")
private String name;
@ApiModelProperty(value = "联系人", example = "芋艿")
private String contactName;
@ApiModelProperty(value = "联系手机", example = "15601691300")
private String contactMobile;
@ApiModelProperty(value = "租户状态0正常 1停用", example = "1")
private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@@ -0,0 +1,41 @@
package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("租户分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SysTenantPageReqVO extends PageParam {
@ApiModelProperty(value = "租户名", example = "芋道")
private String name;
@ApiModelProperty(value = "联系人", example = "芋艿")
private String contactName;
@ApiModelProperty(value = "联系手机", example = "15601691300")
private String contactMobile;
@ApiModelProperty(value = "租户状态0正常 1停用", example = "1")
private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@@ -0,0 +1,19 @@
package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
@ApiModel("租户 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SysTenantRespVO extends SysTenantBaseVO {
@ApiModelProperty(value = "租户编号", required = true, example = "1024")
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@@ -0,0 +1,18 @@
package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("租户更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SysTenantUpdateReqVO extends SysTenantBaseVO {
@ApiModelProperty(value = "租户编号", required = true, example = "1024")
@NotNull(message = "租户编号不能为空")
private Long id;
}

View File

@@ -0,0 +1,36 @@
package cn.iocoder.yudao.adminserver.modules.system.convert.tenant;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantCreateReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExcelVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantRespVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantUpdateReqVO;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* 租户 Convert
*
* @author 芋道源码
*/
@Mapper
public interface SysTenantConvert {
SysTenantConvert INSTANCE = Mappers.getMapper(SysTenantConvert.class);
SysTenantDO convert(SysTenantCreateReqVO bean);
SysTenantDO convert(SysTenantUpdateReqVO bean);
SysTenantRespVO convert(SysTenantDO bean);
List<SysTenantRespVO> convertList(List<SysTenantDO> list);
PageResult<SysTenantRespVO> convertPage(PageResult<SysTenantDO> page);
List<SysTenantExcelVO> convertList02(List<SysTenantDO> list);
}

View File

@@ -0,0 +1,44 @@
package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.tenant;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExportReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantPageReqVO;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 租户 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface SysTenantMapper extends BaseMapperX<SysTenantDO> {
default PageResult<SysTenantDO> selectPage(SysTenantPageReqVO reqVO) {
return selectPage(reqVO, new QueryWrapperX<SysTenantDO>()
.likeIfPresent("name", reqVO.getName())
.likeIfPresent("contact_name", reqVO.getContactName())
.likeIfPresent("contact_mobile", reqVO.getContactMobile())
.eqIfPresent("status", reqVO.getStatus())
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.orderByDesc("id"));
}
default List<SysTenantDO> selectList(SysTenantExportReqVO reqVO) {
return selectList(new QueryWrapperX<SysTenantDO>()
.likeIfPresent("name", reqVO.getName())
.likeIfPresent("contact_name", reqVO.getContactName())
.likeIfPresent("contact_mobile", reqVO.getContactMobile())
.eqIfPresent("status", reqVO.getStatus())
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.orderByDesc("id"));
}
default SysTenantDO selectByName(String name) {
return selectOne("name", name);
}
}

View File

@@ -85,10 +85,12 @@ public interface SysErrorCodeConstants {
ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(1002011000, "短信模板不存在");
ErrorCode SMS_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1002011001, "已经存在编码为【{}】的短信模板");
// ========== 租户模块 1002012000 ==========
ErrorCode TENANT_NOT_EXISTS = new ErrorCode(1002012000, "租户不存在");
// ========== 错误码模块 1002013000 ==========
ErrorCode ERROR_CODE_NOT_EXISTS = new ErrorCode(1002013000, "错误码不存在");
ErrorCode ERROR_CODE_DUPLICATE = new ErrorCode(1002013001, "已经存在编码为【{}】的错误码");
}

View File

@@ -0,0 +1,83 @@
package cn.iocoder.yudao.adminserver.modules.system.service.tenant;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantCreateReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExportReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantPageReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantUpdateReqVO;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
/**
* 租户 Service 接口
*
* @author 芋道源码
*/
public interface SysTenantService {
/**
* 创建租户
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createTenant(@Valid SysTenantCreateReqVO createReqVO);
/**
* 更新租户
*
* @param updateReqVO 更新信息
*/
void updateTenant(@Valid SysTenantUpdateReqVO updateReqVO);
/**
* 删除租户
*
* @param id 编号
*/
void deleteTenant(Long id);
/**
* 获得租户
*
* @param id 编号
* @return 租户
*/
SysTenantDO getTenant(Long id);
/**
* 获得租户列表
*
* @param ids 编号
* @return 租户列表
*/
List<SysTenantDO> getTenantList(Collection<Long> ids);
/**
* 获得租户分页
*
* @param pageReqVO 分页查询
* @return 租户分页
*/
PageResult<SysTenantDO> getTenantPage(SysTenantPageReqVO pageReqVO);
/**
* 获得租户列表, 用于 Excel 导出
*
* @param exportReqVO 查询条件
* @return 租户列表
*/
List<SysTenantDO> getTenantList(SysTenantExportReqVO exportReqVO);
/**
* 获得名字对应的租户
*
* @param name 组户名
* @return 租户
*/
SysTenantDO getTenantByName(String name);
}

View File

@@ -0,0 +1,91 @@
package cn.iocoder.yudao.adminserver.modules.system.service.tenant.impl;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantCreateReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExportReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantPageReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantUpdateReqVO;
import cn.iocoder.yudao.adminserver.modules.system.convert.tenant.SysTenantConvert;
import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.tenant.SysTenantMapper;
import cn.iocoder.yudao.adminserver.modules.system.service.tenant.SysTenantService;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.TENANT_NOT_EXISTS;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
/**
* 租户 Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
public class SysTenantServiceImpl implements SysTenantService {
@Resource
private SysTenantMapper tenantMapper;
@Override
public Long createTenant(SysTenantCreateReqVO createReqVO) {
// 插入
SysTenantDO tenant = SysTenantConvert.INSTANCE.convert(createReqVO);
tenantMapper.insert(tenant);
// 返回
return tenant.getId();
}
@Override
public void updateTenant(SysTenantUpdateReqVO updateReqVO) {
// 校验存在
this.validateTenantExists(updateReqVO.getId());
// 更新
SysTenantDO updateObj = SysTenantConvert.INSTANCE.convert(updateReqVO);
tenantMapper.updateById(updateObj);
}
@Override
public void deleteTenant(Long id) {
// 校验存在
this.validateTenantExists(id);
// 删除
tenantMapper.deleteById(id);
}
private void validateTenantExists(Long id) {
if (tenantMapper.selectById(id) == null) {
throw exception(TENANT_NOT_EXISTS);
}
}
@Override
public SysTenantDO getTenant(Long id) {
return tenantMapper.selectById(id);
}
@Override
public List<SysTenantDO> getTenantList(Collection<Long> ids) {
return tenantMapper.selectBatchIds(ids);
}
@Override
public PageResult<SysTenantDO> getTenantPage(SysTenantPageReqVO pageReqVO) {
return tenantMapper.selectPage(pageReqVO);
}
@Override
public List<SysTenantDO> getTenantList(SysTenantExportReqVO exportReqVO) {
return tenantMapper.selectList(exportReqVO);
}
@Override
public SysTenantDO getTenantByName(String name) {
return tenantMapper.selectByName(name);
}
}

View File

@@ -10,6 +10,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.adminserver.modules.system.framework.codegen.config.CodegenProperties;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
@@ -119,6 +120,8 @@ public class ToolCodegenEngine {
private void initGlobalBindingMap() {
// 全局配置
globalBindingMap.put("basePackage", codegenProperties.getBasePackage());
globalBindingMap.put("baseFrameworkPackage", StrUtil.subBefore(codegenProperties.getBasePackage(),
'.', true) + '.' + "framework");
// 全局 Java Bean
globalBindingMap.put("CommonResultClassName", CommonResult.class.getName());
globalBindingMap.put("PageResultClassName", PageResult.class.getName());
@@ -134,6 +137,7 @@ public class ToolCodegenEngine {
globalBindingMap.put("ServiceExceptionUtilClassName", ServiceExceptionUtil.class.getName());
globalBindingMap.put("DateUtilsClassName", DateUtils.class.getName());
globalBindingMap.put("ExcelUtilsClassName", ExcelUtils.class.getName());
globalBindingMap.put("ObjectUtilsClassName", ObjectUtils.class.getName());
globalBindingMap.put("DictConvertClassName", DictConvert.class.getName());
globalBindingMap.put("OperateLogClassName", OperateLog.class.getName());
globalBindingMap.put("OperateTypeEnumClassName", OperateTypeEnum.class.getName());