# EngineeringRequestNotificationServiceImpl.java

    package cloud.wconnect.frontoffice.service.engineeringrequest.impl;

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.CommonErrorI18nConstant;
    import cloud.wconnect.commonlib.cons.EmailConfigCons;
    import cloud.wconnect.commonlib.cons.FunctionCons;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.pojo.dto.UserDTO;
    import cloud.wconnect.commonlib.pojo.dto.line.PublicFlexMsgParm;
    import cloud.wconnect.commonlib.redis.PropertyI18nRedisService;
    import cloud.wconnect.commonlib.service.UserInternalService;
    import cloud.wconnect.commonlib.service.UsergroupInternalService;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.EmailUtil;
    import cloud.wconnect.commonlib.util.I18nMessageUtils;
    import cloud.wconnect.commonlib.util.LineMessageUtil;
    import cloud.wconnect.frontoffice.cons.PriorityEnum;
    import cloud.wconnect.frontoffice.cons.engineeringrequest.EngineeringRequestCons;
    import cloud.wconnect.frontoffice.cons.engineeringrequest.EngineeringRequestLineNotifyTitleEnum;
    import cloud.wconnect.frontoffice.cons.engineeringrequest.EngineeringRequestNotifyEnum;
    import cloud.wconnect.frontoffice.cons.engineeringrequest.EngineeringRequestStatusEnum;
    import cloud.wconnect.frontoffice.entity.engineeringrequest.EngineeringRequest;
    import cloud.wconnect.frontoffice.entity.engineeringrequest.EngineeringRequestNotification;
    import cloud.wconnect.frontoffice.entity.engineeringrequest.EngineeringRequestNotificationTarget;
    import cloud.wconnect.frontoffice.mapper.engineeringrequest.EngineeringRequestNotificationMapper;
    import cloud.wconnect.frontoffice.pojo.dto.engineeringrequest.EngineeringRequestNotificationDTO;
    import cloud.wconnect.frontoffice.pojo.dto.engineeringrequest.EngineeringRequestNotificationTargetDTO;
    import cloud.wconnect.frontoffice.pojo.vo.engineeringrequest.EngineeringRequestEmailVO;
    import cloud.wconnect.frontoffice.service.engineeringrequest.IEngineeringRequestNotificationService;
    import cloud.wconnect.frontoffice.service.engineeringrequest.IEngineeringRequestNotificationTargetService;
    import com.alibaba.fastjson.JSONObject;
    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.Maps;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.i18n.LocaleContextHolder;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

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

    /**
     * <p>
     * 服务实现类
     * </p>
     *
     * @author yyt
     * @since 2023-05-10
     */
    @Service
    @DS("logbook")
    public class EngineeringRequestNotificationServiceImpl extends ServiceImpl<EngineeringRequestNotificationMapper, EngineeringRequestNotification> implements IEngineeringRequestNotificationService {

        @Autowired
        private IEngineeringRequestNotificationTargetService engineeringRequestNotificationTargetService;
        @Autowired
        private PropertyI18nRedisService propertyI18nRedisService;
        @Autowired
        private UsergroupInternalService usergroupInternalService;
        @Autowired
        private UserInternalService userInternalService;
        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private LineMessageUtil lineMessageUtil;
        @Autowired
        private I18nMessageUtils i18nMessageUtils;

        @Value("${here.link.maintenance-requests.detail}")
        private String detailPage;

        /**
         * 获取通知
         *
         * @param propertyId 资产 id
         * @return 通知
         * @author yyt
         * @date 2023/3/25
         */
        public EngineeringRequestNotification getEngineeringRequestNotification(Integer propertyId) {
            return getOne(new QueryWrapper<EngineeringRequestNotification>().lambda()
                    .eq(EngineeringRequestNotification::getPropertyId, propertyId));
        }

        /**
         * 获取邮件通知默认主题
         *
         * @param propertyName 资产名称
         * @param locale       多语言
         * @return 默认主题
         * @author yyt
         * @date 2024/11/18
         **/
        @Override
        public String getDefaultSubject(String propertyName, Locale locale) {
            return i18nMessageUtils.message(EngineeringRequestCons.DEFAULT_SUBJECT, locale,
                    i18nMessageUtils.message(FunctionCons.ENGINEERING_REQUEST, locale), propertyName);
        }

        /**
         * 根据操作类型，获取邮件通知默认主题
         *
         * @param propertyId           资产 id
         * @param engineeringRequestId engineering request id
         * @param operation            操作
         * @return 默认主题
         * @author yyt
         * @date 2024/11/18
         **/
        @Override
        public String getDefaultSubject(Integer propertyId, Integer engineeringRequestId, int operation) {
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);
            String language = propertyDTO.getLanguage();
            return i18nMessageUtils.message(EngineeringRequestNotifyEnum.getI18nCode(operation), language,
                    i18nMessageUtils.message(FunctionCons.ENGINEERING_REQUEST, language), engineeringRequestId, propertyDTO.getName());
        }

        /**
         * 创建 line msg
         *
         * @param engineeringRequest   EngineeringRequest
         * @param operation 操作（create、update、accept、resolve、comment）
         * @return line msg
         * @author yyt
         * @date 2023/11/29
         */
        @Override
        public JSONObject generateLineMsg(EngineeringRequest engineeringRequest, int operation) {
            LinkedHashMap<String, String> map = Maps.newLinkedHashMapWithExpectedSize(3);
            map.put("NO", engineeringRequest.getId().toString());
            map.put("Contact Phone Number", engineeringRequest.getContactInfo());

            PropertyDTO property = propertyI18nRedisService.get(engineeringRequest.getPropertyId());
            String language = property.getLanguage();
            String title = EngineeringRequestLineNotifyTitleEnum.getI18nCode(operation);
            return lineMessageUtil.generatePublicFlexMsg(new PublicFlexMsgParm(property.getName(), property.getId(),
                    i18nMessageUtils.message(FunctionCons.ENGINEERING_REQUEST, language),
                    title, detailPage + "?id=" + engineeringRequest.getId() + "&property=" + property.getAbbr() +
                    "&tenant=" + property.getTenantSymbol(), map));
        }

        /**
         * 封装邮件内容
         *
         * @param engineeringRequest Engineering Request
         * @return EngineeringRequestEmailVO
         * @author yyt
         * @date 2023/3/29
         */
        @Override
        public EngineeringRequestEmailVO packageEmailContent(EngineeringRequest engineeringRequest) {
            EngineeringRequestEmailVO emailVO = new EngineeringRequestEmailVO();
            emailVO.setId(engineeringRequest.getId());

            PropertyDTO propertyDTO = propertyI18nRedisService.get(engineeringRequest.getPropertyId());
            String language = propertyDTO.getLanguage();

            emailVO.setPropertyName(propertyDTO.getName());
            emailVO.setFunctionName(i18nMessageUtils.message(FunctionCons.ENGINEERING_REQUEST, language));

            Integer priority = engineeringRequest.getPriority();
            emailVO.setPriority(i18nMessageUtils.message(PriorityEnum.getInfoByCode(priority), language));
            emailVO.setPriorityInt(priority);

            emailVO.setContactInfo(engineeringRequest.getContactInfo());
            emailVO.setComments(StringUtils.isEmpty(engineeringRequest.getComments()) ? "--" : EmailUtil.changeLine(engineeringRequest.getComments()));
            emailVO.setHereLink(detailPage + "?id=" + engineeringRequest.getId() + "&property=" + propertyDTO.getAbbr() +
                    "&tenant=" + propertyDTO.getTenantSymbol());

            Integer status = engineeringRequest.getTicketStatus();
            emailVO.setStatus(i18nMessageUtils.message(EngineeringRequestStatusEnum.getI18nCode(status), language));
            emailVO.setStatusInt(status);

            return emailVO;
        }

        /**
         * 新增 notification
         *
         * @param propertyId      资产 id
         * @param notificationDTO 配置内容
         * @param userId          操作人
         * @return 通知 id
         * @author yyt
         * @date 2023/3/30
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public Integer saveNotification(int propertyId, EngineeringRequestNotificationDTO notificationDTO, int userId) {
            EngineeringRequestNotification emailTypeNotification = beanMapper.map(notificationDTO, EngineeringRequestNotification.class);
            emailTypeNotification.setPropertyId(propertyId);
            emailTypeNotification.setNotifyType(notificationDTO.getType());
            emailTypeNotification.setUpdateBy(userId);
            emailTypeNotification.setUpdateTime(DateTimeUtils.nowTimestamp());
            baseMapper.saveOrUpdate(emailTypeNotification);

            if (emailTypeNotification.getId() > 0) {
                engineeringRequestNotificationTargetService.clearNotificationTarget(emailTypeNotification.getId());
            }

            engineeringRequestNotificationTargetService.saveBatch(emailTypeNotification.getId(), propertyId, notificationDTO);

            return emailTypeNotification.getId();
        }

        /**
         * 校验通知存在
         *
         * @param id 通知 id
         * @return 通知
         * @author yyt
         * @date 2023/3/30
         */
        @Override
        public EngineeringRequestNotification checkExist(int id) {
            EngineeringRequestNotification notification = getById(id);
            if (Objects.isNull(notification)) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_FOUND,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "the engineeringRequestNotification is not found;id:" + id);
            }
            return notification;
        }

        /**
         * 获取通知
         *
         * @param propertyId 资产 id
         * @return 通知
         * @author yyt
         * @date 2024/11/18
         **/
        @Override
        public EngineeringRequestNotification get(Integer propertyId) {
            return getOne(new QueryWrapper<EngineeringRequestNotification>().lambda()
                    .eq(EngineeringRequestNotification::getPropertyId, propertyId));
        }

        /**
         * 获取通知
         *
         * @param propertyId 资产 id
         * @return 邮件通知
         * @author yyt
         * @date 2026/1/27
         */
        @Override
        public EngineeringRequestNotificationDTO getNotificationDTO(int propertyId) {
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);
            Locale locale = LocaleContextHolder.getLocale();
            String defaultSubject = getDefaultSubject(propertyDTO.getName(), locale);
            EngineeringRequestNotification notification = get(propertyId);
            if (Objects.isNull(notification)) {
                return new EngineeringRequestNotificationDTO(defaultSubject);
            }

            List<EngineeringRequestNotificationTarget> notificationTargets = engineeringRequestNotificationTargetService.list(notification.getId());

            List<Integer> userIds = notificationTargets.stream().filter(item -> item.getSource() == EmailConfigCons.SOURCE_USER)
                    .map(EngineeringRequestNotificationTarget::getIdentityId).distinct().toList();
            List<Integer> userGroupIds = notificationTargets.stream().filter(item -> item.getSource() == EmailConfigCons.SOURCE_USERGROUP)
                    .map(EngineeringRequestNotificationTarget::getIdentityId).distinct().toList();
            Integer tenantId = propertyDTO.getTenantId();
            Map<Integer, UserDTO> userById = userInternalService.getUserMapByIds(tenantId, userIds);
            Map<Integer, String> userGroupNameById = usergroupInternalService.getUserGroupNameByIds(tenantId, propertyId, userGroupIds);
            notificationTargets.forEach(item -> {
                if (item.getSource() == EmailConfigCons.SOURCE_USER) {
                    item.setIdentityName(userById.get(item.getIdentityId()).getName());
                    item.setEmail(userById.get(item.getIdentityId()).getEmail());
                }
                if (item.getSource() == EmailConfigCons.SOURCE_USERGROUP) {
                    item.setIdentityName(userGroupNameById.get(item.getIdentityId()));
                }
            });

            Map<Integer, List<EngineeringRequestNotificationTarget>> targetsByTargetType = notificationTargets.stream()
                    .collect(Collectors.groupingBy(EngineeringRequestNotificationTarget::getTargetType));
            EngineeringRequestNotificationDTO configDTO = beanMapper.map(notification, EngineeringRequestNotificationDTO.class);
            configDTO.setType(notification.getNotifyType());
            configDTO.setDefaultSubject(defaultSubject);
            configDTO.setToList(beanMapper.mapList(targetsByTargetType.get(EmailConfigCons.TARGET_TYPE_TO), EngineeringRequestNotificationTargetDTO.class));
            configDTO.setCcList(beanMapper.mapList(targetsByTargetType.get(EmailConfigCons.TARGET_TYPE_CC), EngineeringRequestNotificationTargetDTO.class));
            return configDTO;
        }

    }