# CompRoomApproveController.java

    package cloud.wconnect.frontoffice.controller.comproom;

    import cloud.wconnect.commonlib.annotation.ApiId;
    import cloud.wconnect.commonlib.component.SessionContext;
    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.CommonErrorI18nConstant;
    import cloud.wconnect.commonlib.cons.EmailConfigCons;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.exception.ForbiddenException;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.pojo.dto.UserDTO;
    import cloud.wconnect.commonlib.pojo.dto.UsergroupDTO;
    import cloud.wconnect.commonlib.redis.PropertyI18nRedisService;
    import cloud.wconnect.commonlib.service.RoleInternalService;
    import cloud.wconnect.commonlib.service.UserInternalService;
    import cloud.wconnect.commonlib.service.UsergroupInternalService;
    import cloud.wconnect.commonlib.util.I18nMessageUtils;
    import cloud.wconnect.frontoffice.entity.comproom.CompRoomApproveLevel;
    import cloud.wconnect.frontoffice.pojo.dto.comproom.CompRoomApproveCCDTO;
    import cloud.wconnect.frontoffice.pojo.dto.comproom.CompRoomApproveLevelDTO;
    import cloud.wconnect.frontoffice.pojo.dto.comproom.CompRoomApproveUserDTO;
    import cloud.wconnect.frontoffice.service.comproom.ICompRoomApproveConfigService;
    import cloud.wconnect.frontoffice.service.comproom.ICompRoomApproveLevelService;
    import com.google.common.collect.Sets;
    import org.apache.commons.collections.CollectionUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;

    import jakarta.validation.Valid;

    import java.text.MessageFormat;
    import java.util.*;
    import java.util.stream.Collectors;

    /**
     * comp room功能审批控制层
     *
     * @author lichen
     * @date 2023/8/22
     */
    @RestController
    @RequestMapping("/comp-room/approve-config")
    public class CompRoomApproveController {

        @Autowired
        private RoleInternalService roleInternalService;
        @Autowired
        private SessionContext sessionContext;
        @Autowired
        private ICompRoomApproveLevelService compRoomApproveLevelService;
        @Autowired
        private ICompRoomApproveConfigService compRoomApproveConfigService;
        @Autowired
        private UserInternalService userInternalService;
        @Autowired
        private UsergroupInternalService usergroupInternalService;
        @Autowired
        private PropertyI18nRedisService propertyI18nRedisService;
        @Autowired
        private I18nMessageUtils i18nMessageUtils;

        /**
         * 查询资产审批配置
         *
         * @param property 资产标识
         * @return java.util.List<cloud.wconnect.frontoffice.pojo.dto.badguest.BadGuestApproveLevelDTO>
         * @author lichen
         * @date 2023/8/22
         */
        @ApiId(551)
        @GetMapping
        public List<CompRoomApproveLevelDTO> list(String property) {
            int propertyId = sessionContext.getPropertyId(property);
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);
            return compRoomApproveLevelService.list(propertyDTO);
        }

        /**
         * 保存审批层级
         *
         * @param property        资产标识
         * @param approveLevelDTO 审批级别dto
         * @return java.util.Map
         * @author lichen
         * @date 2023/8/22
         */
        @ApiId(552)
        @PostMapping
        public Map save(String property, @Valid @RequestBody CompRoomApproveLevelDTO approveLevelDTO) {
            int propertyId = sessionContext.getPropertyId(property);
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);

            approveLevelDTO.setPropertyId(propertyId);
            //获取当前保存的审核用户集合
            List<Integer> userIds = approveLevelDTO.getUsers().stream().map(CompRoomApproveUserDTO::getId).collect(Collectors.toList());
            //校验用户不能重复
            if (Sets.newHashSet(userIds).size() != userIds.size()) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_CANNOT_REPEAT,
                        i18nMessageUtils.getErrorParamMapNotNeedTranslate("userIds"),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "approve user cannot repeat");
            }

            if (approveLevelDTO.getId() > BaseConstant.ZERO) {
                //校验用户是否重复
                compRoomApproveConfigService.checkUserIsRepeat(propertyId, userIds, approveLevelDTO.getId());
                //校验审批人和抄送对象
                checkApproverAndCC(propertyDTO, userIds, approveLevelDTO.getCcList());
                //校验数据是否存在
                CompRoomApproveLevel oriCompRoomApproveLevel = compRoomApproveLevelService.checkIsExist(approveLevelDTO.getId());
                //校验是否属于当前资产
                checkBelong(oriCompRoomApproveLevel, propertyId);
                //index 不能修改
                approveLevelDTO.setApproveIndex(oriCompRoomApproveLevel.getApproveIndex());
                //修改
                compRoomApproveLevelService.update(oriCompRoomApproveLevel, approveLevelDTO);
            } else {
                //校验用户是否重复
                compRoomApproveConfigService.checkUserIsRepeat(propertyId, userIds, null);
                //校验审批人和抄送对象
                checkApproverAndCC(propertyDTO, userIds, approveLevelDTO.getCcList());
                //新增
                compRoomApproveLevelService.save(approveLevelDTO);
            }
            return Collections.emptyMap();
        }

        /**
         * 删除层级
         *
         * @param property 资产标识
         * @param id       审批层级id
         * @return java.util.Map
         * @author lichen
         * @date 2023/8/22
         */
        @ApiId(553)
        @DeleteMapping
        public Map remove(String property, @RequestParam(name = "id") Integer id) {
            int propertyId = sessionContext.getPropertyId(property);
            //校验数据是否存在
            CompRoomApproveLevel oriCompRoomApproveLevel = compRoomApproveLevelService.checkIsExist(id);
            //校验是否属于当前资产
            checkBelong(oriCompRoomApproveLevel, propertyId);
            compRoomApproveLevelService.remove(oriCompRoomApproveLevel);
            return Collections.emptyMap();
        }

        /**
         * 查询审批角色用户
         *
         * @param property 资产标识
         * @return java.util.List<cloud.wconnect.commonlib.pojo.dto.UserDTO>
         * @author lichen
         * @date 2023/8/22
         */
        @ApiId(554)
        @GetMapping("/approve-user")
        public List<UserDTO> approveUser(String property) {
            int propertyId = sessionContext.getPropertyId(property);
            Integer tenantId = sessionContext.getTenantSymbolBO().getId();

            return roleInternalService.getUsers(tenantId, propertyId, BaseConstant.COMP_ROOM_APPROVE_ROLE);
        }

        /**
         * 校验审批层级是否归属于当前资产
         *
         * @param compRoomApproveLevel 审批层级数据
         * @param propertyId           资产id
         * @return void
         * @author lichen
         * @date 2023/8/22
         */
        private void checkBelong(CompRoomApproveLevel compRoomApproveLevel, Integer propertyId) {
            if (!compRoomApproveLevel.getPropertyId().equals(propertyId)) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(), BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        MessageFormat.format("The approveLevel not belong current property, compRoomApproveLevelId:{0},approveLevelPropertyId:{1},currentPropertyId:{2}"
                                , compRoomApproveLevel.getId(), compRoomApproveLevel.getPropertyId(), propertyId));
            }
        }

        /**
         * 校验审批人和抄送对象是否存在
         *
         * @param propertyDTO  资产DTO
         * @param approverList 审批人集合
         * @param ccList       抄送人集合
         * @return void
         * @author lichen
         * @date 2024/3/11
         */
        private void checkApproverAndCC(PropertyDTO propertyDTO, List<Integer> approverList, List<CompRoomApproveCCDTO> ccList) {
            //按照用户来源分组
            Map<Integer, List<Integer>> source2IdentityIdList = ccList.stream()
                    .collect(Collectors.groupingBy(CompRoomApproveCCDTO::getSource, Collectors.mapping(CompRoomApproveCCDTO::getIdentityId, Collectors.toList())));
            List<Integer> userIdsByCC = source2IdentityIdList.getOrDefault(EmailConfigCons.SOURCE_USER, Collections.emptyList());
            List<Integer> usergroupIds = source2IdentityIdList.getOrDefault(EmailConfigCons.SOURCE_USERGROUP, Collections.emptyList());

            //校验是否重复
            if (userIdsByCC.size() != Sets.newHashSet(userIdsByCC).size()) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_CANNOT_REPEAT,
                        i18nMessageUtils.getErrorParamMapNotNeedTranslate("userIds"),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "user cannot repeat");
            }
            if (usergroupIds.size() != Sets.newHashSet(usergroupIds).size()) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_CANNOT_REPEAT,
                        i18nMessageUtils.getErrorParamMapNotNeedTranslate("userGroupIds"),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "usergroup cannot repeat");
            }
            List<String> manualEmails = ccList.stream().filter(cc -> cc.getSource() == EmailConfigCons.SOURCE_MANUAL)
                    .map(CompRoomApproveCCDTO::getEmail).collect(Collectors.toList());
            if (manualEmails.size() != Sets.newHashSet(manualEmails).size()) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_CANNOT_REPEAT,
                        i18nMessageUtils.getErrorParamMapNotNeedTranslate("manualEmails"),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "manual email cannot repeat");
            }

            //用户集合
            Set<Integer> allUserIds = new HashSet<>();
            allUserIds.addAll(approverList);
            allUserIds.addAll(userIdsByCC);
            List<UserDTO> allUsers = userInternalService.getUsers(propertyDTO.getTenantId(), allUserIds);
            //校验是否存在
            if (allUserIds.size() != allUsers.size()) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_EXIST,
                        i18nMessageUtils.getErrorParamMapNotNeedTranslate("userId"),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "The user not exist");
            }

            //校验用户组是否存在
            if (CollectionUtils.isNotEmpty(usergroupIds)) {
                List<UsergroupDTO> usergroups = usergroupInternalService.getUsergroups(propertyDTO.getTenantId(), propertyDTO.getId(), usergroupIds);
                if (usergroupIds.size() != usergroups.size()) {
                    throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_EXIST,
                            i18nMessageUtils.getErrorParamMapNotNeedTranslate("userGroupId"),
                            BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                            "The user group not exist");
                }
            }
        }
    }