# CbCaseApproveLevelController.java

    package cloud.wconnect.finance.controller.chargeback;

    import cloud.wconnect.commonlib.annotation.ApiId;
    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.component.SessionContext;
    import cloud.wconnect.commonlib.cons.*;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.exception.ForbiddenException;
    import cloud.wconnect.commonlib.pojo.dto.UserDTO;
    import cloud.wconnect.commonlib.pojo.dto.UsergroupDTO;
    import cloud.wconnect.commonlib.pojo.dto.group.Addition;
    import cloud.wconnect.commonlib.pojo.dto.group.Edition;
    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.finance.entity.chargeback.CbCaseApproveLevel;
    import cloud.wconnect.finance.pojo.dto.chargeback.CbCaseApproveLevelDTO;
    import cloud.wconnect.finance.pojo.dto.chargeback.CbCaseApproveLevelUserDTO;
    import cloud.wconnect.finance.pojo.dto.chargeback.CbCaseCCDTO;
    import cloud.wconnect.finance.pojo.dto.chargeback.SaveApproveLevelDTO;
    import cloud.wconnect.finance.pojo.query.chargeback.CbCaseApproveLevelQuery;
    import cloud.wconnect.finance.service.chargeback.ICbCaseApproveLevelService;
    import com.google.common.collect.Lists;
    import com.google.common.collect.Sets;
    import jakarta.validation.Valid;
    import org.apache.commons.collections.CollectionUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.annotation.*;

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

    /**
     * <p>
     * case 审批层级表 前端控制器
     * </p>
     *
     * @author yyt
     * @since 2023-08-22
     */
    @RestController
    @RequestMapping("/charge-back/approve-config")
    public class CbCaseApproveLevelController {

        @Autowired
        private SessionContext sessionContext;
        @Lazy
        @Autowired
        private ICbCaseApproveLevelService cbCaseApproveLevelService;
        @Autowired
        private UserInternalService userInternalService;
        @Autowired
        private UsergroupInternalService usergroupInternalService;
        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private RoleInternalService roleInternalService;
        @Autowired
        private I18nMessageUtils i18nMessageUtils;

        /**
         * 查询审批配置
         *
         * @param property 资产标识
         * @param query    搜索条件
         * @return 审批配置
         * @author yyt
         * @date 2023/8/24
         */
        @ApiId(585)
        @GetMapping
        public List<CbCaseApproveLevelDTO> listApproveLevelDTO(String property, @Validated(Addition.class) CbCaseApproveLevelQuery query) {
            return cbCaseApproveLevelService.listApproveLevelDTO(sessionContext.getTenantSymbolBO().getId(), sessionContext.getPropertyId(property), query);
        }

        /**
         * 获取指定角色下用户
         *
         * @param property 资产标识
         * @param query    查询条件
         * @return 角色下用户
         * @author yyt
         * @date 2023/8/24
         */
        @ApiId(583)
        @GetMapping("/role/user")
        public List<CbCaseApproveLevelUserDTO> listApproveUserByRole(String property,
                                                                     @Validated(Edition.class) CbCaseApproveLevelQuery query) {
            int role = 0;
            switch (query.getType()) {
                case CbCaseApproveLevelQuery.TYPE_HOTEL_HANDLE:
                    role = BaseConstant.CHARGEBACK_HOTEL_HANDLE_ROLE;
                    break;
                case CbCaseApproveLevelQuery.TYPE_FINANCE_HANDLE:
                    role = BaseConstant.CHARGEBACK_FINANCE_HANDLE_ROLE;
                    break;
                case CbCaseApproveLevelQuery.TYPE_HOTEL_APPROVE:
                    role = BaseConstant.CHARGEBACK_HOTEL_APPROVE_ROLE;
                    break;
                case CbCaseApproveLevelQuery.TYPE_FINANCE_APPROVE:
                    role = BaseConstant.CHARGEBACK_FINANCE_APPROVE_ROLE;
                    break;
                default:
            }
            return beanMapper.mapList(roleInternalService.getUsers(sessionContext.getTenantSymbolBO().getId(),
                    sessionContext.getPropertyId(property), role), CbCaseApproveLevelUserDTO.class);
        }

        /**
         * 保存审批层级
         *
         * @param id              审批层级 id
         * @param property        资产标识
         * @param approveLevelDTO 审批配置
         * @return {}
         * @author yyt
         * @date 2023/8/24
         */
        @ApiId(586)
        @PostMapping("/{id:\\d+}")
        public Map save(@PathVariable long id, String property, @Valid @RequestBody SaveApproveLevelDTO approveLevelDTO) {
            Integer propertyId = sessionContext.getPropertyId(property);

            if (CollectionUtils.isNotEmpty(approveLevelDTO.getUsers())) {
                // 选择用户不能重复
                Set<Integer> userIds = new HashSet<>(approveLevelDTO.getUsers());
                if (userIds.size() != approveLevelDTO.getUsers().size()) {
                    throw new BadRequestException(CommonErrorI18nConstant.APPROVE_USER_REPEAT,
                            BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "Users at the same level cannot be the same.");
                }
            }

            // 检查目标（用户/用户组）是否存在
            checkTargetExist(propertyId, approveLevelDTO);

            if (id == BaseConstant.ZERO) {
                cbCaseApproveLevelService.save(propertyId, approveLevelDTO);
            } else {
                CbCaseApproveLevel approveLevel = cbCaseApproveLevelService.checkExist(id);
                checkBelong(approveLevel, propertyId);
                cbCaseApproveLevelService.update(approveLevel, approveLevelDTO);
            }

            return Collections.emptyMap();
        }

        /**
         * 检查目标（用户/用户组）是否存在
         *
         * @param propertyId      资产 id
         * @param approveLevelDTO 审批层级
         * @author yyt
         * @date 2024/3/9
         **/
        private void checkTargetExist(Integer propertyId, SaveApproveLevelDTO approveLevelDTO) {
            Set<Integer> userIds = Sets.newHashSet();
            List<Integer> userGroupIds = Lists.newArrayList();
            List<Integer> users = approveLevelDTO.getUsers();
            if (CollectionUtils.isNotEmpty(users)) {
                userIds.addAll(users);
            }
            List<CbCaseCCDTO> cc = approveLevelDTO.getCc();
            if (CollectionUtils.isNotEmpty(cc)) {
                Map<Integer, List<Integer>> targetIdByUserSource = cc.stream().collect(Collectors.groupingBy(CbCaseCCDTO::getSource,
                        Collectors.collectingAndThen(Collectors.toList(), item -> item.stream().map(CbCaseCCDTO::getIdentityId).toList())));
                userIds.addAll(targetIdByUserSource.getOrDefault(EmailConfigCons.SOURCE_USER, Collections.emptyList()));
                userGroupIds.addAll(targetIdByUserSource.getOrDefault(EmailConfigCons.SOURCE_USERGROUP, Collections.emptyList()));
            }
            Integer tenantId = sessionContext.getTenantSymbolBO().getId();
            List<UserDTO> userDTOs = userInternalService.getUsers(tenantId, userIds);
            if (userDTOs.size() != userIds.size()) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_EXIST,
                        i18nMessageUtils.getErrorParamMapNeedTranslate(CommonFieldI18nConstant.USER),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "the user is not found");
            }
            List<UsergroupDTO> usergroups = usergroupInternalService.getUsergroups(tenantId, propertyId, userGroupIds);
            if (usergroups.size() != userGroupIds.size()) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_EXIST,
                        i18nMessageUtils.getErrorParamMapNeedTranslate(CommonFieldI18nConstant.USER_GROUP),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "the userGroup is not found");
            }
        }

        /**
         * 删除审批层级
         *
         * @param id              审批层级 id
         * @param property        资产标识
         * @return {}
         * @author yyt
         * @date 2023/8/26
         */
        @ApiId(587)
        @DeleteMapping("/{id:\\d+}")
        public Map delete(@PathVariable long id, String property) {
            CbCaseApproveLevel approveLevel = cbCaseApproveLevelService.checkExist(id);
            checkBelong(approveLevel, sessionContext.getPropertyId(property));

            cbCaseApproveLevelService.delete(approveLevel);

            return Collections.emptyMap();
        }

        /**
         * 校验数据归属
         *
         * @param approveLevel 审批层级
         * @param propertyId   资产 id
         * @author yyt
         * @date 2023/8/25
         */
        private void checkBelong(CbCaseApproveLevel approveLevel, Integer propertyId) {
            if (!approveLevel.getPropertyId().equals(propertyId)) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(), "the property id parameter is different from " +
                        "the property id of the cbCaseApproveLevel;propertyId:" + propertyId + ",cbCaseApproveLevelPropertyId:" +
                        approveLevel.getPropertyId() + ",cbCaseApproveLevelId:" + approveLevel.getId());
            }
        }

    }