# DbEmailConfigServiceImpl.java

    package cloud.wconnect.workperformance.service.database.impl;

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.EmailConfigCons;
    import cloud.wconnect.commonlib.cons.FunctionCons;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.pojo.dto.UserDTO;
    import cloud.wconnect.commonlib.service.UserInternalService;
    import cloud.wconnect.commonlib.service.UsergroupInternalService;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.I18nMessageUtils;
    import cloud.wconnect.workperformance.cons.database.DbNotifyTypeEnum;
    import cloud.wconnect.workperformance.entity.database.DbEmailConfig;
    import cloud.wconnect.workperformance.entity.database.DbEmailTarget;
    import cloud.wconnect.workperformance.mapper.database.DbEmailConfigMapper;
    import cloud.wconnect.workperformance.pojo.dto.database.notification.DbEmailConfigDTO;
    import cloud.wconnect.workperformance.pojo.dto.database.notification.DbEmailTargetDTO;
    import cloud.wconnect.workperformance.service.database.IDbEmailConfigService;
    import cloud.wconnect.workperformance.service.database.IDbEmailTargetService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.google.common.collect.Lists;
    import jakarta.annotation.Resource;
    import org.apache.commons.collections.CollectionUtils;
    import org.springframework.context.i18n.LocaleContextHolder;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import java.util.Collections;
    import java.util.List;
    import java.util.Map;
    import java.util.Objects;
    import java.util.stream.Collectors;

    /**
     * <p>
     * Database email config 服务实现类
     * </p>
     *
     * @author zc
     * @since 2025-12-02
     */
    @Service
    @DS("database")
    public class DbEmailConfigServiceImpl extends ServiceImpl<DbEmailConfigMapper, DbEmailConfig> implements IDbEmailConfigService {

        @Resource
        private IDbEmailTargetService emailTargetService;
        @Resource
        private UserInternalService userInternalService;
        @Resource
        private UsergroupInternalService usergroupInternalService;
        @Resource
        private I18nMessageUtils i18nMessageUtils;
        @Resource
        private BeanMapper beanMapper;

        /**
         * 保存邮件配置信息
         *
         * @param propertyId     资产 id
         * @param operatorId     操作人 id
         * @param emailConfigDTO 邮件配置信息
         * @return 邮件配置 id
         * @author zc
         * @date 2025/12/02
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public int save(int propertyId, int operatorId, DbEmailConfigDTO emailConfigDTO) {
            DbEmailConfig emailConfig = beanMapper.map(emailConfigDTO, DbEmailConfig.class, config -> {
                config.setPropertyId(propertyId);
                config.setUpdateBy(operatorId);
                config.setUpdateTime(DateTimeUtils.nowTimestamp());
            });
            baseMapper.insertOrUpdateByUnique(emailConfig);

            // 删除原有数据
            emailTargetService.removeByConfigId(emailConfig.getId());

            List<DbEmailTarget> emailTargetList = Lists.newArrayList();
            emailTargetList.addAll(convert(propertyId, EmailConfigCons.TARGET_TYPE_TO, emailConfig.getId(), emailConfigDTO.getToList()));
            emailTargetList.addAll(convert(propertyId, EmailConfigCons.TARGET_TYPE_CC, emailConfig.getId(), emailConfigDTO.getCcList()));
            emailTargetService.saveBatch(emailTargetList);

            return emailConfig.getId();
        }

        /**
         * 转换为实体类对象
         *
         * @param propertyId property id
         * @param targetType 邮件类型
         * @param configId   邮件配置 id
         * @param list       EmailTargetDTO 数据
         * @return EmailTarget 集合
         * @author zc
         * @date 2025/12/02
         */
        private List<DbEmailTarget> convert(int propertyId, int targetType, int configId, List<DbEmailTargetDTO> list) {
            if (CollectionUtils.isEmpty(list)) {
                return Collections.emptyList();
            }
            return list.stream().map(item -> beanMapper.map(item, DbEmailTarget.class, target -> {
                target.setPropertyId(propertyId);
                target.setConfigId(configId);
                target.setTargetType(targetType);
                // 用户来源是 manual 时，用户 id 记录为 0，保存用户名
                if (target.getSource() == EmailConfigCons.USER_SOURCE_MANUAL) {
                    target.setIdentityId(EmailConfigCons.ZERO);
                    target.setUsername(item.getIdentityName());
                } else {
                    target.setUsername(null);
                    target.setEmail(null);
                }
            })).collect(Collectors.toList());
        }

        /**
         * 获取邮件配置DTO
         *
         * @param propertyDTO 资产 DTO
         * @param type        邮件类型
         * @return 邮件配置DTO
         * @author zc
         * @date 2025/12/02
         */
        @Override
        public DbEmailConfigDTO getEmailConfigDTO(PropertyDTO propertyDTO, int type) {
            String defaultSubject = generateDefaultSubject(type, propertyDTO.getName());
            DbEmailConfig emailConfig = getEmailConfig(propertyDTO.getId(), type);
            if (Objects.isNull(emailConfig)) {
                DbEmailConfigDTO emailConfigDTO = new DbEmailConfigDTO();
                emailConfigDTO.setType(type);
                emailConfigDTO.setDefaultSubject(defaultSubject);
                return emailConfigDTO;
            }
            // 获取接收人、抄送人
            List<DbEmailTarget> emailTargetList = emailTargetService.listByConfigId(emailConfig.getId());

            Map<Integer, List<Integer>> source2IdentityIdList = emailTargetList.stream()
                    .collect(Collectors.groupingBy(DbEmailTarget::getSource,
                            Collectors.mapping(DbEmailTarget::getIdentityId, Collectors.toList())));
            // 用户
            Map<Integer, UserDTO> userId2UserDTO = userInternalService.getUserMapByIds(propertyDTO.getTenantId(),
                    source2IdentityIdList.getOrDefault(EmailConfigCons.SOURCE_USER, Collections.emptyList()));
            // 用户组
            Map<Integer, String> userGroupId2Name = usergroupInternalService.getUserGroupNameByIds(propertyDTO.getTenantId(),
                    propertyDTO.getId(), source2IdentityIdList.getOrDefault(EmailConfigCons.SOURCE_USERGROUP, Collections.emptyList()));

            // 通知对象按照通知类型分组
            Map<Integer, List<DbEmailTargetDTO>> targetsByTargetType = beanMapper.mapList(emailTargetList,
                    DbEmailTargetDTO.class, (entity, dto) -> {
                        int source = dto.getSource();
                        int identityId = dto.getIdentityId();
                        switch (source) {
                            case EmailConfigCons.SOURCE_USER:
                                UserDTO userDTO = userId2UserDTO.get(identityId);
                                if (Objects.nonNull(userDTO)) {
                                    dto.setIdentityName(userDTO.getName());
                                    dto.setEmail(userDTO.getEmail());
                                }
                                break;
                            case EmailConfigCons.SOURCE_USERGROUP:
                                dto.setIdentityName(userGroupId2Name.get(identityId));
                                break;
                            case EmailConfigCons.SOURCE_MANUAL:
                                dto.setIdentityName(entity.getUsername());
                                break;
                            default:
                                break;
                        }
                    }).stream().collect(Collectors.groupingBy(DbEmailTargetDTO::getTargetType));
            return beanMapper.map(emailConfig, DbEmailConfigDTO.class, dto -> {
                dto.setDefaultSubject(defaultSubject);
                dto.setToList(targetsByTargetType.get(EmailConfigCons.TARGET_TYPE_TO));
                dto.setCcList(targetsByTargetType.get(EmailConfigCons.TARGET_TYPE_CC));
            });
        }

        /**
         * 生成邮件默认主题
         *
         * @param type         邮件类型
         * @param propertyName 资产名称
         * @return java.lang.String
         * @author zc
         * @date 2025/12/02
         */
        private String generateDefaultSubject(int type, String propertyName) {
            String language = LocaleContextHolder.getLocale().toString();
            String functionName = i18nMessageUtils.message(FunctionCons.DATABASE, language);
            return i18nMessageUtils.message(DbNotifyTypeEnum.getDefaultSubjectI18nCode(type), language, functionName, propertyName);
        }

        /**
         * 获取邮件配置
         *
         * @param propertyId 资产 id
         * @param type       邮件类型
         * @return 邮件配置
         * @author zc
         * @date 2025/12/02
         */
        @Override
        public DbEmailConfig getEmailConfig(int propertyId, int type) {
            return getOne(new QueryWrapper<DbEmailConfig>().lambda()
                    .eq(DbEmailConfig::getPropertyId, propertyId)
                    .eq(DbEmailConfig::getType, type));
        }
    }