xda il y a 2 ans
Parent
commit
ec60177532

+ 13 - 0
src/main/java/com/winhc/repal/RepalApplication.java

@@ -1,10 +1,16 @@
 package com.winhc.repal;
 
+import com.winhc.repal.constant.Constant;
+import com.winhc.repal.enums.PermissionEnum;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 import org.springframework.cloud.openfeign.EnableFeignClients;
 
+import javax.annotation.PostConstruct;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
 @EnableDiscoveryClient
 @EnableFeignClients
 @SpringBootApplication
@@ -14,4 +20,11 @@ public class RepalApplication {
         SpringApplication.run(RepalApplication.class, args);
     }
 
+
+
+    @PostConstruct
+    public void initPermissionCode() {
+        Constant.PERMISSION_MAP = Arrays.stream(PermissionEnum.values()).collect(Collectors.toMap(PermissionEnum::getCode, PermissionEnum::getMsg));
+    }
+
 }

+ 9 - 0
src/main/java/com/winhc/repal/constant/Constant.java

@@ -1,5 +1,8 @@
 package com.winhc.repal.constant;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * @Description: Constant
  * @Author: xda
@@ -12,5 +15,11 @@ public class Constant {
      */
     public static final String USER_PERMISSION_KEY = "winhc:repal:userPermission:";
 
+    /**
+     *  权限编码
+     */
+    public static Map<String, String> PERMISSION_MAP = new HashMap<>();
+
+
 
 }

+ 1 - 5
src/main/java/com/winhc/repal/controller/RepalGroupController.java

@@ -44,11 +44,7 @@ public class RepalGroupController {
         return BeanResponse.success(CodeMsg.SUCCESS, repalGroupService.getGroupMemberList(dto));
     }
 
-    @ApiOperation("成员管理列表")
-    @RequestMapping(value = "/roleMember", method = RequestMethod.GET)
-    public BeanResponse<List<GroupRoleMemberVO>> getGroupRoleMemberList() {
-        return BeanResponse.success(CodeMsg.SUCCESS, repalGroupService.getGroupRoleMemberList());
-    }
+
 
 
 

+ 34 - 0
src/main/java/com/winhc/repal/controller/RepalMemberController.java

@@ -0,0 +1,34 @@
+package com.winhc.repal.controller;
+
+import com.winhc.common.base.BeanResponse;
+import com.winhc.common.enums.CodeMsg;
+import com.winhc.repal.model.vo.GroupRoleMemberVO;
+import com.winhc.repal.service.RepalGroupMemberService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * @Description: TODO
+ * @Author: xda
+ * @Date: 2022/5/10 16:11
+ */
+@Api(tags = "组织成员")
+@RestController
+@RequestMapping(value = "/member")
+public class RepalMemberController {
+
+    @Autowired
+    private RepalGroupMemberService repalGroupMemberService;
+
+    @ApiOperation("成员管理列表")
+    @RequestMapping(value = "/roleMember", method = RequestMethod.GET)
+    public BeanResponse<List<GroupRoleMemberVO>> getGroupRoleMemberList() {
+        return BeanResponse.success(CodeMsg.SUCCESS, repalGroupMemberService.getGroupRoleMemberList());
+    }
+}

+ 60 - 0
src/main/java/com/winhc/repal/controller/RepalRoleController.java

@@ -0,0 +1,60 @@
+package com.winhc.repal.controller;
+
+import com.winhc.common.base.BeanResponse;
+import com.winhc.common.enums.CodeMsg;
+import com.winhc.repal.annotation.RolePermission;
+import com.winhc.repal.enums.PermissionEnum;
+import com.winhc.repal.model.dto.MemberRoleDTO;
+import com.winhc.repal.model.vo.GroupRoleVO;
+import com.winhc.repal.model.vo.RolePermissionVO;
+import com.winhc.repal.service.RepalGroupRoleService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * @Description: 组织角色管理
+ * @Author: xda
+ * @Date: 2022/5/10 16:11
+ */
+@Api(tags = "组织角色管理")
+@RestController
+@RequestMapping(value = "/role")
+public class RepalRoleController {
+
+    @Autowired
+    private RepalGroupRoleService repalGroupRoleService;
+
+    @ApiOperation("新增角色")
+    @RequestMapping(value = "/add", method = RequestMethod.POST)
+    @RolePermission(permission = PermissionEnum.ROLE_SETUP)
+    public BeanResponse<Boolean> addRole(@RequestBody MemberRoleDTO dto) {
+        return BeanResponse.success(CodeMsg.SUCCESS, repalGroupRoleService.addRole(dto));
+    }
+
+    @ApiOperation("删除角色")
+    @RequestMapping(value = "/del/{roleId}", method = RequestMethod.POST)
+    @RolePermission(permission = PermissionEnum.ROLE_SETUP)
+    public BeanResponse<Boolean> deleteRoleById(@PathVariable("roleId") Long roleId) {
+        return BeanResponse.success(CodeMsg.SUCCESS, repalGroupRoleService.deleteRoleById(roleId));
+    }
+
+
+    @ApiOperation("角色列表")
+    @RequestMapping(value = "/list", method = RequestMethod.GET)
+    public BeanResponse<List<GroupRoleVO>> getGroupRoleList() {
+        return BeanResponse.success(CodeMsg.SUCCESS, repalGroupRoleService.getGroupRoleList());
+    }
+
+
+    @ApiOperation("获取角色对应的权限列表")
+    @RequestMapping(value = "/permission/{roleId}", method = RequestMethod.GET)
+    @RolePermission(permission = PermissionEnum.ROLE_SETUP)
+    public BeanResponse<List<RolePermissionVO>> getPermissionList(@PathVariable("roleId") Long roleId) {
+        return BeanResponse.success(CodeMsg.SUCCESS, repalGroupRoleService.getPermissionList(roleId));
+    }
+
+}

+ 23 - 0
src/main/java/com/winhc/repal/model/dto/MemberRoleDTO.java

@@ -0,0 +1,23 @@
+package com.winhc.repal.model.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @Description: MemberRoleDTO
+ * @Author: xda
+ * @Date: 2022/5/10 16:15
+ */
+@ApiModel("新增角色dto")
+@Data
+public class MemberRoleDTO {
+
+    @ApiModelProperty("权限列表")
+    private List<String> permissionCodeList;
+
+    @ApiModelProperty("角色name")
+    private String roleName;
+}

+ 27 - 0
src/main/java/com/winhc/repal/model/vo/GroupRoleVO.java

@@ -0,0 +1,27 @@
+package com.winhc.repal.model.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @Description: 组织角色
+ * @Author: xda
+ * @Date: 2022/5/10 19:50
+ */
+@Data
+@ApiModel("组织角色")
+public class GroupRoleVO {
+
+    @ApiModelProperty("角色name")
+    private String roleName;
+
+    @ApiModelProperty("角色id")
+    private Long roleId;
+
+    @ApiModelProperty("角色类型,1系统角色(不可修改).2用户自定义角色")
+    private Integer roleType;
+
+
+
+}

+ 21 - 0
src/main/java/com/winhc/repal/model/vo/RolePermissionVO.java

@@ -0,0 +1,21 @@
+package com.winhc.repal.model.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @Description: RolePermissionVO
+ * @Author: xda
+ * @Date: 2022/5/10 20:03
+ */
+@Data
+@ApiModel("角色权限vo")
+public class RolePermissionVO {
+
+    @ApiModelProperty("角色code")
+    private String permissionCode;
+
+    @ApiModelProperty("角色name")
+    private String permissionName;
+}

+ 38 - 0
src/main/java/com/winhc/repal/service/RepalGroupRoleService.java

@@ -2,6 +2,9 @@ package com.winhc.repal.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.winhc.repal.entity.RepalGroupRole;
+import com.winhc.repal.model.dto.MemberRoleDTO;
+import com.winhc.repal.model.vo.GroupRoleVO;
+import com.winhc.repal.model.vo.RolePermissionVO;
 
 import java.util.List;
 
@@ -23,4 +26,39 @@ public interface RepalGroupRoleService extends IService<RepalGroupRole> {
     List<RepalGroupRole> getRoleByIdList(List<Long> idList);
 
 
+    /**
+     * 新增角色
+     * @param dto dto
+     * @return java.lang.Boolean
+     * @author xda
+     * @date 2022/5/10 16:17
+     */
+    Boolean addRole(MemberRoleDTO dto);
+
+    /**
+     * 获取组织角色列表
+     * @return java.util.List<com.winhc.repal.model.vo.GroupRoleVO>
+     * @author xda
+     * @date 2022/5/10 19:54
+     */
+    List<GroupRoleVO> getGroupRoleList();
+
+    /**
+     * 获取角色对应的权限
+     * @param roleId roleId
+     * @return java.util.List<com.winhc.repal.model.vo.RolePermissionVO>
+     * @author xda
+     * @date 2022/5/10 20:05
+     */
+    List<RolePermissionVO> getPermissionList(Long roleId);
+
+    /**
+     * 删除角色
+     * @param roleId roleId
+     * @return java.lang.Boolean
+     * @author xda
+     * @date 2022/5/10 20:19
+     */
+    Boolean deleteRoleById(Long roleId);
+
 }

+ 0 - 10
src/main/java/com/winhc/repal/service/RepalGroupService.java

@@ -6,9 +6,6 @@ import com.winhc.repal.entity.RepalGroup;
 import com.winhc.repal.model.dto.InitGroupDTO;
 import com.winhc.repal.model.dto.PageDTO;
 import com.winhc.repal.model.vo.GroupMemberVo;
-import com.winhc.repal.model.vo.GroupRoleMemberVO;
-
-import java.util.List;
 
 
 /**
@@ -38,12 +35,5 @@ public interface RepalGroupService extends IService<RepalGroup> {
      */
     VOPage<GroupMemberVo> getGroupMemberList(PageDTO dto);
 
-    /**
-     * 获取组织角色成员列表
-     * @return java.util.List<com.winhc.repal.model.vo.GroupRoleMemberVO>
-     * @author xda
-     * @date 2022/5/10 14:44
-     */
-    List<GroupRoleMemberVO> getGroupRoleMemberList();
 
 }

+ 22 - 0
src/main/java/com/winhc/repal/service/RepalRolePermissionService.java

@@ -3,6 +3,7 @@ package com.winhc.repal.service;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.winhc.repal.entity.RepalRolePermission;
 
+import java.util.List;
 import java.util.Set;
 
 
@@ -43,4 +44,25 @@ public interface RepalRolePermissionService extends IService<RepalRolePermission
      */
     Boolean processUserPermissionCache(Long userId, Set<String> codeSet);
 
+
+    /**
+     * 为角色添加权限
+     * @param roleId roleId
+     * @param perCodeList perCodeList
+     * @return java.lang.Boolean
+     * @author xda
+     * @date 2022/5/10 19:36
+     */
+    Boolean addRolePermission(Long roleId, List<String> perCodeList);
+
+    /**
+     * 获取角色对应的权限列表
+     * @param roleId roleId
+     * @return java.util.List<com.winhc.repal.entity.RepalRolePermission>
+     * @author xda
+     * @date 2022/5/10 20:14
+     */
+    List<RepalRolePermission> getRolePermissionList(Long roleId);
+
+
 }

+ 1 - 1
src/main/java/com/winhc/repal/service/impl/RepalBookServiceImpl.java

@@ -230,7 +230,7 @@ public class RepalBookServiceImpl extends ServiceImpl<RepalBookMapper, RepalBook
         if (CollUtil.isEmpty(recordList)) {
             return new ArrayList<>();
         }
-        Map<LocalDate, List<RepalChangeRecord>> map = recordList.stream().collect(Collectors.groupingBy(t -> t.getTimeCreated().toLocalDate()));
+        Map<LocalDate, List<RepalChangeRecord>> map = recordList.stream().collect(Collectors.groupingBy(RepalChangeRecord::getRecordDate));
         return map.entrySet().stream().map(t -> {
             ReturnedMoneyVO vo = new ReturnedMoneyVO();
             vo.setDate(t.getKey());

+ 96 - 0
src/main/java/com/winhc/repal/service/impl/RepalGroupRoleServiceImpl.java

@@ -1,12 +1,33 @@
 package com.winhc.repal.service.impl;
 
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.winhc.common.enums.CodeMsg;
+import com.winhc.common.exception.CommonException;
+import com.winhc.repal.entity.RepalGroupMember;
 import com.winhc.repal.entity.RepalGroupRole;
+import com.winhc.repal.entity.RepalRolePermission;
+import com.winhc.repal.enums.DeletedStatusEnum;
+import com.winhc.repal.enums.RoleTypeEnum;
+import com.winhc.repal.model.dto.MemberRoleDTO;
+import com.winhc.repal.model.vo.GroupRoleVO;
+import com.winhc.repal.model.vo.RolePermissionVO;
 import com.winhc.repal.repository.RepalGroupRoleMapper;
+import com.winhc.repal.service.RepalGroupMemberService;
 import com.winhc.repal.service.RepalGroupRoleService;
+import com.winhc.repal.service.RepalRolePermissionService;
+import com.winhc.repal.util.UserContextUtil;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * @description RepalGroupRole 接口实现类
@@ -17,8 +38,83 @@ import java.util.List;
 public class RepalGroupRoleServiceImpl extends ServiceImpl<RepalGroupRoleMapper, RepalGroupRole> implements RepalGroupRoleService {
 
 
+    @Autowired
+    private RepalRolePermissionService repalRolePermissionService;
+
+    @Autowired
+    private RepalGroupMemberService repalGroupMemberService;
+
+
     @Override
     public List<RepalGroupRole> getRoleByIdList(List<Long> idList) {
         return this.listByIds(idList);
     }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean addRole(MemberRoleDTO dto) {
+        long groupId = repalGroupMemberService.getUserGroupId(UserContextUtil.getUser().getUserId());
+        // 添加角色
+        RepalGroupRole repalGroupRole = new RepalGroupRole();
+        repalGroupRole.setRepalGroupId(groupId);
+        repalGroupRole.setRoleType(RoleTypeEnum.CUSTOMER.getCode());
+        repalGroupRole.setRoleName(dto.getRoleName());
+        repalGroupRole.setRepalGroupId(groupId);
+        this.save(repalGroupRole);
+        // 为角色添加权限
+        repalRolePermissionService.addRolePermission(repalGroupRole.getId(), dto.getPermissionCodeList());
+        return true;
+    }
+
+    @Override
+    public List<GroupRoleVO> getGroupRoleList() {
+        long userId = UserContextUtil.getUser().getUserId();
+        List<RepalGroupRole> groupRoleList = this.list(Wrappers.lambdaQuery(RepalGroupRole.class)
+                .in(RepalGroupRole::getRepalGroupId, Stream.of(0, repalGroupMemberService.getUserGroupId(userId)).collect(Collectors.toList()))
+                .eq(RepalGroupRole::getDeleted, DeletedStatusEnum.NORMAL.getCode())
+                .orderByDesc(RepalGroupRole::getId));
+        return groupRoleList.stream().map(role -> {
+            GroupRoleVO vo = new GroupRoleVO();
+            vo.setRoleId(role.getId());
+            vo.setRoleType(role.getRoleType());
+            vo.setRoleName(role.getRoleName());
+            return vo;
+        }).collect(Collectors.toList());
+    }
+
+    @Override
+    public List<RolePermissionVO> getPermissionList(Long roleId) {
+        List<RepalRolePermission> permissionList = repalRolePermissionService.getRolePermissionList(roleId);
+        if (CollUtil.isEmpty(permissionList)) {
+            return new ArrayList<>();
+        }
+        return permissionList.stream().map(permission -> {
+            RolePermissionVO vo = new RolePermissionVO();
+            vo.setPermissionName(permission.getPermissionName());
+            vo.setPermissionCode(permission.getPermissionCode());
+            return vo;
+        }).collect(Collectors.toList());
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean deleteRoleById(Long roleId) {
+        long userId = UserContextUtil.getUser().getUserId();
+        RepalGroupRole repalGroupRole = this.getById(roleId);
+        if (RoleTypeEnum.SYSTEM.getCode().equals(repalGroupRole.getRoleType())) {
+            throw new CommonException(CodeMsg.FAILED, "系统角色无法删除");
+        }
+        if (!repalGroupRole.getRepalGroupId().equals(repalGroupMemberService.getUserGroupId(userId))) {
+            throw new CommonException(CodeMsg.FAILED, "该角色不属于该组织");
+        }
+        if (repalGroupMemberService.count(Wrappers.lambdaQuery(RepalGroupMember.class)
+                .eq(RepalGroupMember::getRoleId, roleId)
+                .eq(RepalGroupMember::getDeleted, DeletedStatusEnum.NORMAL.getCode())) > 0) {
+            throw new CommonException(CodeMsg.FAILED, "有成员为该角色,无法删除,请先改变该成员的角色后再删除");
+        }
+        this.update(Wrappers.lambdaUpdate(RepalGroupRole.class)
+                .eq(RepalGroupRole::getId, roleId)
+                .set(RepalGroupRole::getDeleted, DeletedStatusEnum.DELETE.getCode()));
+        return true;
+    }
 }

+ 0 - 7
src/main/java/com/winhc/repal/service/impl/RepalGroupServiceImpl.java

@@ -13,7 +13,6 @@ import com.winhc.repal.enums.RoleTypeEnum;
 import com.winhc.repal.model.dto.InitGroupDTO;
 import com.winhc.repal.model.dto.PageDTO;
 import com.winhc.repal.model.vo.GroupMemberVo;
-import com.winhc.repal.model.vo.GroupRoleMemberVO;
 import com.winhc.repal.repository.RepalGroupMapper;
 import com.winhc.repal.service.RepalBookService;
 import com.winhc.repal.service.RepalGroupMemberService;
@@ -26,7 +25,6 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.ArrayList;
-import java.util.List;
 import java.util.Objects;
 import java.util.stream.Collectors;
 
@@ -95,9 +93,4 @@ public class RepalGroupServiceImpl extends ServiceImpl<RepalGroupMapper, RepalGr
         voPage.setDataList(page.getRecords().stream().map(t -> new GroupMemberVo(t.getUserId(), t.getMemberUserName())).collect(Collectors.toList()));
         return voPage;
     }
-
-    @Override
-    public List<GroupRoleMemberVO> getGroupRoleMemberList() {
-        return repalGroupMemberService.getGroupRoleMemberList();
-    }
 }

+ 28 - 0
src/main/java/com/winhc/repal/service/impl/RepalRolePermissionServiceImpl.java

@@ -1,16 +1,20 @@
 package com.winhc.repal.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.winhc.repal.constant.Constant;
 import com.winhc.repal.entity.RepalRolePermission;
+import com.winhc.repal.enums.DeletedStatusEnum;
 import com.winhc.repal.repository.RepalRolePermissionMapper;
 import com.winhc.repal.service.RepalRolePermissionService;
 import com.winhc.repal.util.RedisUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
@@ -53,4 +57,28 @@ public class RepalRolePermissionServiceImpl extends ServiceImpl<RepalRolePermiss
         redisUtil.expire(Constant.USER_PERMISSION_KEY + userId, 7, TimeUnit.DAYS);
         return true;
     }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean addRolePermission(Long roleId, List<String> perCodeList) {
+        if (CollUtil.isEmpty(perCodeList)) {
+            return true;
+        }
+        RepalRolePermission permission;
+        for (String code : perCodeList) {
+            permission = new RepalRolePermission();
+            permission.setPermissionCode(code);
+            permission.setPermissionName(Constant.PERMISSION_MAP.get(code));
+            permission.setRepalGroupRoleId(roleId);
+            this.save(permission);
+        }
+        return true;
+    }
+
+    @Override
+    public List<RepalRolePermission> getRolePermissionList(Long roleId) {
+        return this.list(Wrappers.lambdaQuery(RepalRolePermission.class)
+                .eq(RepalRolePermission::getRepalGroupRoleId, roleId)
+                .eq(RepalRolePermission::getDeleted, DeletedStatusEnum.NORMAL.getCode()));
+    }
 }

+ 13 - 11
src/main/java/com/winhc/repal/util/BillGradeUtil.java

@@ -8,6 +8,7 @@ import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * @Description: BillGradeUtil
@@ -22,17 +23,18 @@ public class BillGradeUtil {
             return new ArrayList<>();
         }
         int total = gradeList.size();
-        long aCount = gradeList.stream().filter("A"::equals).count();;
-        long bCount = gradeList.stream().filter("B"::equals).count();;
-        long cCount = gradeList.stream().filter("C"::equals).count();;
-        long dCount = gradeList.stream().filter("D"::equals).count();;
-        long nCount = gradeList.stream().filter(StrUtil::isNotBlank).count();;
-        return new ArrayList<HomeGradeVO>(){{
-            add(new HomeGradeVO(Math.toIntExact(aCount), new BigDecimal(aCount).divide(new BigDecimal(total), 1, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString()));
-            add(new HomeGradeVO(Math.toIntExact(bCount), new BigDecimal(bCount).divide(new BigDecimal(total), 1, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString()));
-            add(new HomeGradeVO(Math.toIntExact(cCount), new BigDecimal(cCount).divide(new BigDecimal(total), 1, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString()));
-            add(new HomeGradeVO(Math.toIntExact(dCount), new BigDecimal(dCount).divide(new BigDecimal(total), 1, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString()));
-            add(new HomeGradeVO(Math.toIntExact(nCount), new BigDecimal(nCount).divide(new BigDecimal(total), 1, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString()));
+        List<Long> countList = new ArrayList<Long>(){{
+            add(gradeList.stream().filter("A"::equals).count());
+            add(gradeList.stream().filter("B"::equals).count());
+            add(gradeList.stream().filter("C"::equals).count());
+            add(gradeList.stream().filter("D"::equals).count());
+            add(gradeList.stream().filter(StrUtil::isBlank).count());
         }};
+        return countList.stream().map(count -> {
+            HomeGradeVO vo = new HomeGradeVO();
+            vo.setCount(Math.toIntExact(count));
+            vo.setRate(new BigDecimal(count).multiply(new BigDecimal(100)).divide(new BigDecimal(total), 2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString() + "%");
+            return vo;
+        }).collect(Collectors.toList());
     }
 }