# AdjEmailConfigController.java

    package cloud.wconnect.frontoffice.controller.adjustment;

    import cloud.wconnect.commonlib.annotation.ApiId;
    import cloud.wconnect.commonlib.component.SessionContext;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.CommonErrorI18nConstant;
    import cloud.wconnect.commonlib.cons.CommonFieldI18nConstant;
    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.UserInternalService;
    import cloud.wconnect.commonlib.service.UsergroupInternalService;
    import cloud.wconnect.commonlib.util.I18nMessageUtils;
    import cloud.wconnect.frontoffice.cons.adjustment.AdjColumnEnum;
    import cloud.wconnect.frontoffice.cons.adjustment.AdjNotifyConfigTypeEnum;
    import cloud.wconnect.frontoffice.entity.adjustment.AdjEmailConfig;
    import cloud.wconnect.frontoffice.pojo.dto.adjustment.AdjEmailConfigDTO;
    import cloud.wconnect.frontoffice.pojo.dto.adjustment.AdjEmailTargetDTO;
    import cloud.wconnect.frontoffice.service.adjustment.IAdjEmailConfigService;
    import com.google.common.collect.ImmutableMap;
    import com.google.common.collect.Lists;
    import com.google.common.collect.Sets;
    import org.apache.commons.collections4.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;

    /**
     * <p>
     * Adjustment Requests 功能的邮件配置表 前端控制器
     * </p>
     *
     * @author lichen
     * @since 2023-03-30
     */
    @RestController
    @RequestMapping("/adjustment/email-config")
    public class AdjEmailConfigController {

        @Autowired
        private IAdjEmailConfigService adjEmailConfigService;
        @Autowired
        private SessionContext sessionContext;
        @Autowired
        private UserInternalService userInternalService;
        @Autowired
        private UsergroupInternalService usergroupInternalService;
        @Autowired
        private PropertyI18nRedisService propertyI18nRedisService;
        @Autowired
        private I18nMessageUtils i18nMessageUtils;

        /**
         * 保存邮件配置
         *
         * @param property       资产标识
         * @param emailConfigDTO 邮件配置DTO
         * @return java.util.Map
         * @author lichen
         * @date 2024/3/13
         */
        @ApiId(227)
        @PostMapping
        public Map save(String property, @RequestBody @Valid AdjEmailConfigDTO emailConfigDTO) {
            int propertyId = sessionContext.getPropertyId(property);
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);

            ArrayList<Integer> approvingTypeList = Lists.newArrayList(AdjNotifyConfigTypeEnum.SALES_WAIT_FOR_APPROVING.getType(),
                    AdjNotifyConfigTypeEnum.FRONT_DESK_WAIT_FOR_APPROVING.getType(), AdjNotifyConfigTypeEnum.ACCOUTING_WAIT_FOR_APPROVING.getType());
            //校验审批类型的邮件配置开关必须是开启
            if (approvingTypeList.contains(emailConfigDTO.getType()) && !emailConfigDTO.getStatus()) {
                throw new BadRequestException(CommonErrorI18nConstant.MUST_IN_LIST,
                        i18nMessageUtils.getErrorParamMapNeedTranslate(CommonFieldI18nConstant.STATUS, CommonFieldI18nConstant.OPEN),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "The status of the approval type must be Enabled");
            }

            //校验通知对象是否重复以及存在
            checkEmailTarget(propertyDTO, emailConfigDTO);

            if (emailConfigDTO.getId() > 0) {
                //校验是否存在
                AdjEmailConfig oriEmailConfig = checkExistAndBelong(emailConfigDTO.getId(), propertyId);
                //校验type不能修改
                if (!oriEmailConfig.getType().equals(emailConfigDTO.getType())) {
                    throw new BadRequestException(CommonErrorI18nConstant.CANNOT_MODIFIED,
                            i18nMessageUtils.getErrorParamMapNotNeedTranslate("emailConfigType"),
                            BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "The adjustment email config type cannot be modified");
                }
            } else {
                //校验资产是否已经配置邮件
                adjEmailConfigService.checkSole(propertyId, emailConfigDTO.getType());
            }
            //保存邮件配置
            return ImmutableMap.of("id", adjEmailConfigService.save(propertyId, emailConfigDTO));
        }

        /**
         * 查询邮件配置
         *
         * @param property 资产标识
         * @param type     类型
         * @return cloud.wconnect.frontoffice.pojo.dto.adjustment.AdjEmailConfigDTO
         * @author lichen
         * @date 2024/3/13
         */
        @ApiId(228)
        @GetMapping
        public AdjEmailConfigDTO get(String property, @RequestParam(name = "type") Integer type) {
            int propertyId = sessionContext.getPropertyId(property);
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);
            return adjEmailConfigService.getByPropertyIdAndType(propertyDTO, type);
        }

        /**
         * 校验邮件是否存在 和 是否归属于当前资产
         *
         * @param id         主键id
         * @param propertyId 资产Id
         * @return cloud.wconnect.frontoffice.entity.adjustment.AdjEmailConfig
         * @author lichen
         * @date 2024/3/13
         */
        private AdjEmailConfig checkExistAndBelong(Integer id, Integer propertyId) {
            AdjEmailConfig emailConfig = adjEmailConfigService.getById(id);
            if (Objects.isNull(emailConfig)) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_FOUND,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "Adjustment Requests Email Config not found, id=" + id);
            }
            if (emailConfig.getPropertyId().compareTo(propertyId) != 0) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        MessageFormat.format("adjustment email config not belong property, emailConfigId:{0}, belongPropertyId:{1}, currentPropertyId:{2}",
                                emailConfig.getId(), emailConfig.getPropertyId(), propertyId));
            }
            return emailConfig;
        }

        /**
         * 校验通知对象是否合法
         *
         * @param propertyDTO    资产DTO
         * @param emailConfigDTO 邮件配置DTO
         * @return void
         * @author lichen
         * @date 2024/3/11
         */
        private void checkEmailTarget(PropertyDTO propertyDTO, AdjEmailConfigDTO emailConfigDTO) {
            List<AdjEmailTargetDTO> toList = emailConfigDTO.getToList();
            List<AdjEmailTargetDTO> ccList = emailConfigDTO.getCcList();

            List<AdjEmailTargetDTO> allNotifyList = Lists.newArrayList();
            if (CollectionUtils.isNotEmpty(toList)) {
                allNotifyList.addAll(toList);
            }
            if (CollectionUtils.isNotEmpty(ccList)) {
                allNotifyList.addAll(ccList);
            }
            if (CollectionUtils.isEmpty(allNotifyList)) return;

            ArrayList<Integer> notifyTypes = Lists.newArrayList(AdjNotifyConfigTypeEnum.DRAFT_STATISTICS_EACH_TYPE.getType(),
                    AdjNotifyConfigTypeEnum.APPROVED.getType(),
                    AdjNotifyConfigTypeEnum.APPROVING_DAILY_SUMMARY.getType());
            if (notifyTypes.contains(emailConfigDTO.getType())) {
                //校验requestType不能为null
                if (allNotifyList.stream().anyMatch(item -> Objects.isNull(item.getRequestType()))) {
                    throw new BadRequestException(CommonErrorI18nConstant.CANNOT_EMPTY,
                            i18nMessageUtils.getErrorParamMapNeedTranslate(AdjColumnEnum.REQUESTED_BY.getI18nCode()),
                            BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "request type cannot be null");
                }

                //按照requestType分组
                Map<Integer, List<AdjEmailTargetDTO>> requestType2NotifyList = allNotifyList.stream().collect(Collectors.groupingBy(AdjEmailTargetDTO::getRequestType));
                //校验相同的requestType下用户、用户组是否存在 且 是否重复，手动输入的邮箱是否重复
                requestType2NotifyList.values().forEach(list -> checkExistAndRepeat(propertyDTO, list));
            } else {
                //校验requestType必须为null
                if (allNotifyList.stream().anyMatch(item -> Objects.nonNull(item.getRequestType()))) {
                    throw new BadRequestException(CommonErrorI18nConstant.MUST_EMPTY,
                            i18nMessageUtils.getErrorParamMapNeedTranslate(AdjColumnEnum.REQUESTED_BY.getI18nCode()),
                            BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "request type must be null");
                }

                checkExistAndRepeat(propertyDTO, allNotifyList);
            }
        }

        /**
         * 校验用户、用户组是否存在、是否重复，校验手动输入的邮箱是否重复
         *
         * @param propertyDTO     资产DTO
         * @param emailTargetDTOS 通知人集合
         * @return void
         * @author lichen
         * @date 2024/8/23
         */
        private void checkExistAndRepeat(PropertyDTO propertyDTO, List<AdjEmailTargetDTO> emailTargetDTOS) {
            //按照用户来源分组
            Map<Integer, List<Integer>> source2IdentityIdList = emailTargetDTOS.stream()
                    .collect(Collectors.groupingBy(AdjEmailTargetDTO::getSource, Collectors.mapping(AdjEmailTargetDTO::getIdentityId, Collectors.toList())));
            List<Integer> userIds = source2IdentityIdList.getOrDefault(EmailConfigCons.SOURCE_USER, Collections.emptyList());
            List<Integer> usergroupIds = source2IdentityIdList.getOrDefault(EmailConfigCons.SOURCE_USERGROUP, Collections.emptyList());

            //校验用户Id是否重复
            if (userIds.size() != Sets.newHashSet(userIds).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 = emailTargetDTOS.stream().filter(item -> item.getSource() == EmailConfigCons.SOURCE_MANUAL)
                    .map(AdjEmailTargetDTO::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");
            }

            //用户集合
            if (CollectionUtils.isNotEmpty(userIds)) {
                List<UserDTO> allUsers = userInternalService.getUsers(propertyDTO.getTenantId(), userIds);
                //校验是否存在
                if (userIds.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");
                }
            }
        }

    }