# WalkRoomNotifyServiceImpl.java

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

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.cons.EmailConfigCons;
    import cloud.wconnect.commonlib.cons.FunctionCons;
    import cloud.wconnect.commonlib.pojo.dto.NotifyDTO;
    import cloud.wconnect.commonlib.pojo.dto.NotifyIdentityDTO;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.pojo.dto.UserDTO;
    import cloud.wconnect.commonlib.pojo.dto.internationalization.InternationalizationDateTimeDTO;
    import cloud.wconnect.commonlib.pojo.dto.internationalization.InternationalizationNumberDTO;
    import cloud.wconnect.commonlib.pojo.dto.line.PublicFlexMsgParm;
    import cloud.wconnect.commonlib.service.NotifyInternalService;
    import cloud.wconnect.commonlib.service.PropertyInternalService;
    import cloud.wconnect.commonlib.service.UserInternalService;
    import cloud.wconnect.commonlib.util.*;
    import cloud.wconnect.frontoffice.cons.ApproveStatusEnum;
    import cloud.wconnect.frontoffice.cons.FunctionPointEnum;
    import cloud.wconnect.frontoffice.cons.walkroomrequest.WalkRoomApproveTypeEnum;
    import cloud.wconnect.frontoffice.cons.walkroomrequest.WalkRoomFieldI18nConstant;
    import cloud.wconnect.frontoffice.cons.walkroomrequest.WalkRoomRequestNotifyConfigTypeEnum;
    import cloud.wconnect.frontoffice.cons.walkroomrequest.WalkRoomStatusEnum;
    import cloud.wconnect.frontoffice.entity.walkroomrequest.*;
    import cloud.wconnect.frontoffice.pojo.vo.walkroomrequest.notify.WalkRoomDateinNotifyVO;
    import cloud.wconnect.frontoffice.pojo.vo.walkroomrequest.notify.WalkRoomNotifyVO;
    import cloud.wconnect.frontoffice.service.walkroomrequest.*;
    import com.alibaba.fastjson.JSONObject;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.google.common.collect.Lists;
    import com.google.common.collect.Sets;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.lang.Nullable;
    import org.springframework.stereotype.Service;
    import org.thymeleaf.TemplateEngine;
    import org.thymeleaf.context.Context;

    import java.math.BigDecimal;
    import java.text.MessageFormat;
    import java.util.*;
    import java.util.function.Function;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;

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

    /**
     * walkRoom功能 通知业务实现层
     *
     * @author lichen
     * @date 2023/7/11
     */
    @DS("logbook")
    @Service
    @Slf4j
    public class WalkRoomNotifyServiceImpl implements IWalkRoomNotifyService {

        @Autowired
        @Lazy
        private IWalkRoomDateinOtherService walkRoomDateinOtherService;
        @Autowired
        @Lazy
        private IWalkRoomApproveLevelService approveLevelService;
        @Autowired
        private PropertyInternalService propertyInternalService;
        @Autowired
        @Lazy
        private IWalkRoomDateinRateService walkRoomDateinRateService;
        @Autowired
        @Lazy
        private IWalkRoomRequestService walkRoomRequestService;
        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private UserInternalService userInternalService;
        @Autowired
        @Lazy
        private IWalkRoomApproveConfigService approveConfigService;
        @Autowired
        @Lazy
        private IWalkRoomApproveLogService approveLogService;
        @Autowired
        private TemplateEngine templateEngine;
        @Autowired
        private LineMessageUtil lineMessageUtil;
        @Autowired
        private NotifyInternalService notifyInternalService;
        @Autowired
        private I18nMessageUtils i18nMessageUtils;
        @Value("${here.link.walk-room-requests}")
        private String hereLink;
        @Autowired
        private ObjectMapper objectMapper;
        @Autowired
        private IWalkRoomEmailConfigService emailConfigService;

        /**
         * 推送至下一个审批节点时发送审批通知
         * 使用场景：审批层级变更时（i. 改变审批规则 ii. 删除审批层级 iii.审批层级变更审批人）把数据推送至下一个审批层级
         * 当前层级审批完成时，把数据推送至下一个审批层级
         *
         * @param nextApproveLevel     下一个审批节点
         * @param walkRoomDateinOthers 入住明细集合
         * @return void
         * @author lichen
         * @date 2023/7/11
         */
        @Override
        public void pushNextApproveLevelSendApproveNotify(WalkRoomApproveLevel nextApproveLevel, List<WalkRoomDateinOther> walkRoomDateinOthers) {
            if (Objects.isNull(nextApproveLevel)) return;
            if (CollectionUtils.isEmpty(walkRoomDateinOthers)) return;

            //资产id
            Integer propertyId = nextApproveLevel.getPropertyId();
            //审批类型1：sent 2:receive
            Integer approveType = nextApproveLevel.getType();

            //查询邮件配置
            WalkRoomEmailConfig emailConfig = emailConfigService.getByPropertyIdAndType(propertyId, approveType);
            if (Objects.isNull(emailConfig)) {
                emailConfig = new WalkRoomEmailConfig();
                emailConfig.setStatus(true);
            }
            if (!emailConfig.getStatus()) {
                log.warn("Walk Room Request notify approver end, email config is close.");
                return;
            }

            //walkRoom主键id集合
            List<Long> reqIds = walkRoomDateinOthers.stream().map(WalkRoomDateinOther::getReqId).collect(Collectors.toList());
            //入住日期集合
            Set<Integer> dates = walkRoomDateinOthers.stream().map(WalkRoomDateinOther::getDate).collect(Collectors.toSet());
            //查询walkRoom数据
            List<WalkRoomRequest> walkRoomRequests = walkRoomRequestService.listByIds(reqIds);
            Map<Long, WalkRoomRequest> reqId2WalkRoomRequest = walkRoomRequests.stream().collect(toMap(WalkRoomRequest::getId, Function.identity()));
            //查询walk-rate的数据
            Map<String, BigDecimal> reqIdAndDate2Rate = walkRoomDateinRateService.listReqIdAndDateMapByReqIdAndDate(reqIds, dates);
            //查询dateinOther数据
            Map<Long, List<WalkRoomDateinOther>> reqId2DateinOthers = walkRoomDateinOtherService.listByReqIds(reqIds)
                    .stream().collect(Collectors.groupingBy(WalkRoomDateinOther::getReqId));

            //下一个审批节点配置的审批人集合
            List<Integer> approverList = approveConfigService.listByLevelIds(Lists.newArrayList(nextApproveLevel.getId()))
                    .stream().map(WalkRoomApproveConfig::getUserId).collect(toList());

            //资产id集合
            Set<Integer> propertyIds = walkRoomRequests.stream().flatMap(item -> Stream.of(item.getFromPropertyId(), item.getToPropertyId())).collect(Collectors.toSet());
            Map<Integer, PropertyDTO> propertyId2Property = propertyInternalService.getPropertyId2Property(propertyIds);

            //资产对象
            PropertyDTO propertyDTO = propertyId2Property.get(propertyId);
            //获取租户id
            Integer tenantId = propertyDTO.getTenantId();

            //用户id集合
            Set<Integer> userIds = walkRoomRequests.stream().flatMap(item -> Stream.of(item.getLastSentBy(), item.getAgentUserId())).collect(Collectors.toSet());
            Set<Integer> updateBys = walkRoomDateinOthers.stream().map(WalkRoomDateinOther::getUpdateBy).collect(Collectors.toSet());
            userIds.addAll(updateBys);
            List<UserDTO> users = userInternalService.getUsers(tenantId, userIds);
            Map<Integer, String> userId2Name = users.stream().collect(Collectors.toMap(UserDTO::getId, UserDTO::getName));

            List<WalkRoomDateinNotifyVO> walkRoomDateinNotifyVOList = Lists.newArrayListWithCapacity(walkRoomDateinOthers.size());
            for (WalkRoomDateinOther walkRoomDateinOther : walkRoomDateinOthers) {
                //过滤掉入住日等于离店日期的数据
                WalkRoomRequest walkRoomRequest = reqId2WalkRoomRequest.get(walkRoomDateinOther.getReqId());
                if (walkRoomDateinOther.getDate().equals(walkRoomRequest.getCheckOutDate())) continue;

                //当crsNumber 为空时，使用之前非空的crsNumber
                if (StringUtils.isBlank(walkRoomDateinOther.getCrsNumber())) {
                    List<WalkRoomDateinOther> allWalkRoomDateinOthers = reqId2DateinOthers.get(walkRoomDateinOther.getReqId());
                    List<WalkRoomDateinOther> earlyDateinOthers = allWalkRoomDateinOthers.stream()
                            .filter(item -> StringUtils.isNotBlank(item.getCrsNumber()) && item.getDate() < walkRoomDateinOther.getDate())
                            .sorted(Comparator.comparingLong(WalkRoomDateinOther::getDate).reversed())
                            .collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(earlyDateinOthers)) {
                        WalkRoomDateinOther earlyDateinOther = earlyDateinOthers.get(0);
                        walkRoomDateinOther.setCrsNumber(earlyDateinOther.getCrsNumber());
                        walkRoomDateinOther.setStatus(earlyDateinOther.getStatus());
                    }
                }
                //入住记录转化为vo
                WalkRoomDateinNotifyVO walkRoomDateinNotifyVO = convertDateinOtherToVO(walkRoomDateinOther, propertyId2Property, userId2Name, approveType);
                //walk room数据转化为vo
                WalkRoomNotifyVO walkRoomNotifyVO = convertWalkRoomRequestsToVO(walkRoomRequest, propertyId2Property, userId2Name, approveType);
                walkRoomDateinNotifyVO.setWalkRoomNotifyVO(walkRoomNotifyVO);
                //设置walk rate
                String rateKey = WalkRoomDateinRate.generateKey(walkRoomDateinOther.getReqId(), walkRoomDateinOther.getDate());
                //国际化walk rate
                InternationalizationNumberDTO number = propertyDTO.getInternationalization().getNumber();
                walkRoomDateinNotifyVO.setRate(reqIdAndDate2Rate.get(rateKey));
                walkRoomDateinNotifyVO.setRateStr(InternationalizationUtils.formatAmountViewValue(reqIdAndDate2Rate.get(rateKey),
                        number.getCalculationRule(), number.getCurrency()));

                walkRoomDateinNotifyVOList.add(walkRoomDateinNotifyVO);
            }

            //发送入住记录的审批通知
            sendDateinApproveNotify(walkRoomDateinNotifyVOList, approveType, propertyDTO, approverList, nextApproveLevel.getCc(), emailConfig.getSubject());
        }

        /**
         * walk room数据变化（新增、修改）时发送审批通知
         *
         * @param reqId walk room主鍵id
         * @return void
         * @author lichen
         * @date 2023/7/18
         */
        @Override
        public void walkRoomChangeSendApproveNotify(Long reqId) {
            //查询walk room数据
            WalkRoomRequest walkRoomRequest = walkRoomRequestService.getById(reqId);
            //查询walk room的入住记录
            List<WalkRoomDateinOther> walkRoomDateinOthers = walkRoomDateinOtherService.listByReqIds(Collections.singletonList(walkRoomRequest.getId()));
            if (CollectionUtils.isEmpty(walkRoomDateinOthers)) return;

            List<Long> dateInOtherIds = walkRoomDateinOthers.stream().map(WalkRoomDateinOther::getId).collect(toList());
            //查询入住记录对应的审批日志
            Map<String, Long> otherIdAndpropertyId2ApproveLogCount = approveLogService.listByDateinOtherIds(dateInOtherIds).stream()
                    .collect(Collectors.groupingBy(item -> WalkRoomApproveLog.otherIdAndPropertyIdGenerateKey(item.getDateinOtherId(), item.getPropertyId()),
                            Collectors.counting()));

            //过滤出发送方还未开始审批的数据
            List<WalkRoomDateinOther> sentNotStartApproveList = walkRoomDateinOthers.stream()
                    .filter(item -> {
                        if (item.getSentApproveStatus() == ApproveStatusEnum.APPROVEING.getStatus()) {
                            Long approveLogCount = otherIdAndpropertyId2ApproveLogCount.get(WalkRoomApproveLog.otherIdAndPropertyIdGenerateKey(item.getId(), item.getFromPropertyId()));
                            return Objects.isNull(approveLogCount) || approveLogCount == BaseConstant.LONG_ZERO;
                        } else {
                            return false;
                        }
                    }).collect(Collectors.toList());

            //过滤出接收方还未开始审批的数据
            List<WalkRoomDateinOther> receiveNotStartApproveList = walkRoomDateinOthers.stream()
                    .filter(item -> {
                        if (item.getReceiveApproveStatus() == ApproveStatusEnum.APPROVEING.getStatus()) {
                            Long approveLogCount = otherIdAndpropertyId2ApproveLogCount.get(WalkRoomApproveLog.otherIdAndPropertyIdGenerateKey(item.getId(), item.getToPropertyId()));
                            return Objects.isNull(approveLogCount) || approveLogCount == BaseConstant.LONG_ZERO;
                        } else {
                            return false;
                        }
                    }).collect(Collectors.toList());

            if (CollectionUtils.isEmpty(sentNotStartApproveList) && CollectionUtils.isEmpty(receiveNotStartApproveList))
                return;

            Integer fromPropertyId = walkRoomRequest.getFromPropertyId();
            Integer toPropertyId = walkRoomRequest.getToPropertyId();
            List<Integer> propertyIds = Lists.newArrayList(fromPropertyId, toPropertyId);

            //查询出资产配置的第一级审批层级
            Map<String, WalkRoomApproveLevel> propertyIdAndType2FirstApproveLevel = approveLevelService.listFirstApproveLevel(propertyIds);
            //审批人集合
            List<Long> allLevelIds = propertyIdAndType2FirstApproveLevel.values().stream().map(WalkRoomApproveLevel::getId).toList();
            Map<Long, List<Integer>> levelId2UserIds = approveConfigService.listByLevelIds(allLevelIds).stream().collect(groupingBy(WalkRoomApproveConfig::getLevelId,
                    mapping(WalkRoomApproveConfig::getUserId, toList())));
            //查询walk-rate的数据
            Map<Integer, BigDecimal> date2Rate = walkRoomDateinRateService.listDateMapByReqIdAndDate(reqId, Collections.emptyList());

            //查询资产信息
            Map<Integer, PropertyDTO> propertyId2Property = propertyInternalService.getPropertyId2Property(propertyIds);

            //租户id
            Integer tenantId = propertyId2Property.get(fromPropertyId).getTenantId();
            //查询用户集合
            Set<Integer> userIds = walkRoomDateinOthers.stream().map(WalkRoomDateinOther::getUpdateBy).collect(toSet());
            userIds.add(walkRoomRequest.getLastSentBy());
            userIds.add(walkRoomRequest.getAgentUserId());
            List<UserDTO> users = userInternalService.getUsers(tenantId, userIds);
            Map<Integer, String> userId2Name = users.stream().collect(Collectors.toMap(UserDTO::getId, UserDTO::getName));

            //发送方邮件配置
            WalkRoomEmailConfig sentEmailConfig = emailConfigService.getByPropertyIdAndType(fromPropertyId, WalkRoomApproveTypeEnum.SENT.getCode());
            if (Objects.isNull(sentEmailConfig)) {
                sentEmailConfig = new WalkRoomEmailConfig();
                sentEmailConfig.setStatus(true);
            }
            if (sentEmailConfig.getStatus() && CollectionUtils.isNotEmpty(sentNotStartApproveList)) {//发送方邮件通知
                WalkRoomApproveLevel firstApproveLevel = propertyIdAndType2FirstApproveLevel.get(
                        WalkRoomApproveLevel.generateKey(fromPropertyId, WalkRoomApproveTypeEnum.SENT.getCode()));
                if (Objects.nonNull(firstApproveLevel)) {
                    List<Integer> userIdsByApproveLevel = levelId2UserIds.get(firstApproveLevel.getId());
                    //发送通知
                    sendWalkRoomApproveNotify(fromPropertyId, walkRoomRequest, sentNotStartApproveList,
                            propertyId2Property, userId2Name, date2Rate, WalkRoomApproveTypeEnum.SENT.getCode(),
                            userIdsByApproveLevel, firstApproveLevel.getCc(), sentEmailConfig.getSubject());
                }
            }

            //接收方邮件配置
            WalkRoomEmailConfig receiveEmailConfig = emailConfigService.getByPropertyIdAndType(toPropertyId, WalkRoomApproveTypeEnum.RECEIVE.getCode());
            if (Objects.isNull(receiveEmailConfig)) {
                receiveEmailConfig = new WalkRoomEmailConfig();
                receiveEmailConfig.setStatus(true);
            }
            if (receiveEmailConfig.getStatus() && CollectionUtils.isNotEmpty(receiveNotStartApproveList)) {
                WalkRoomApproveLevel firstApproveLevel = propertyIdAndType2FirstApproveLevel.get(
                        WalkRoomApproveLevel.generateKey(toPropertyId, WalkRoomApproveTypeEnum.RECEIVE.getCode()));
                if (Objects.nonNull(firstApproveLevel)) {
                    List<Integer> userIdsByApproveLevel = levelId2UserIds.get(firstApproveLevel.getId());
                    //发送通知
                    sendWalkRoomApproveNotify(toPropertyId, walkRoomRequest, receiveNotStartApproveList,
                            propertyId2Property, userId2Name, date2Rate, WalkRoomApproveTypeEnum.RECEIVE.getCode(),
                            userIdsByApproveLevel, firstApproveLevel.getCc(), receiveEmailConfig.getSubject());
                }
            }
        }

        /**
         * 入住记录审批信息重置后发送审批通知
         *
         * @param needApproveNotifyDateinOthers 需要发送审批通知的入住记录集合
         * @return void
         * @author lichen
         * @date 2023/7/21
         */
        @Override
        public void dateinOtherApproveResetSendApproveNotify(List<WalkRoomDateinOther> needApproveNotifyDateinOthers) {
            if (CollectionUtils.isEmpty(needApproveNotifyDateinOthers)) return;
            List<Long> dateInOtherIds = needApproveNotifyDateinOthers.stream().map(WalkRoomDateinOther::getId).collect(toList());

            //所有的资产ID集合
            Set<Integer> allPropertyIds = needApproveNotifyDateinOthers.stream()
                    .flatMap(item -> Stream.of(item.getFromPropertyId(), item.getToPropertyId())).collect(toSet());
            //邮件配置集合
            List<WalkRoomEmailConfig> emailConfigs = emailConfigService.list(new LambdaQueryWrapper<WalkRoomEmailConfig>()
                    .in(WalkRoomEmailConfig::getPropertyId, allPropertyIds));
            //查询资产邮件配置的状态集合
            Map<String, Boolean> propertyIdAndType2EmailConfigStatus = emailConfigs.stream().collect(toMap(
                    item -> WalkRoomEmailConfig.generateKey(item.getPropertyId(), item.getType())
                    , WalkRoomEmailConfig::getStatus));
            //查询资产邮件配置的主题集合
            Map<String, String> propertyIdAndType2EmailConfigSubject = emailConfigs.stream().collect(toMap(
                    item -> WalkRoomEmailConfig.generateKey(item.getPropertyId(), item.getType())
                    , WalkRoomEmailConfig::getSubject));

            //查询入住记录对应的审批日志
            Map<String, Long> otherIdAndpropertyId2ApproveLogCount = approveLogService.listByDateinOtherIds(dateInOtherIds).stream()
                    .collect(Collectors.groupingBy(item -> WalkRoomApproveLog.otherIdAndPropertyIdGenerateKey(item.getDateinOtherId(), item.getPropertyId()),
                            Collectors.counting()));

            //发送方未开始审批 且 审批配置状态为开启 的数据
            List<WalkRoomDateinOther> sentNotStartApproveList = needApproveNotifyDateinOthers.stream().filter(item -> {
                if (item.getSentApproveStatus() == ApproveStatusEnum.APPROVEING.getStatus()) {
                    Long approveLogCount = otherIdAndpropertyId2ApproveLogCount.get(WalkRoomApproveLog.otherIdAndPropertyIdGenerateKey(item.getId(), item.getFromPropertyId()));
                    //是否未开始审批
                    Boolean isNotStartApprove = Objects.isNull(approveLogCount) || approveLogCount == BaseConstant.LONG_ZERO;
                    //发送方邮件配置开关
                    String emailConfigKey = WalkRoomEmailConfig.generateKey(item.getFromPropertyId(), WalkRoomApproveTypeEnum.SENT.getCode());
                    Boolean emailConfigStatus = propertyIdAndType2EmailConfigStatus.getOrDefault(emailConfigKey, true);
                    return isNotStartApprove && emailConfigStatus;
                } else {
                    return false;
                }
            }).collect(Collectors.toList());
            //接收方未开始审批的数据
            List<WalkRoomDateinOther> receiveNotStartApproveList = needApproveNotifyDateinOthers.stream().filter(item -> {
                if (item.getReceiveApproveStatus() == ApproveStatusEnum.APPROVEING.getStatus()) {
                    Long approveLogCount = otherIdAndpropertyId2ApproveLogCount.get(WalkRoomApproveLog.otherIdAndPropertyIdGenerateKey(item.getId(), item.getToPropertyId()));
                    //是否未开始审批
                    Boolean isNotStartApprove = Objects.isNull(approveLogCount) || approveLogCount == BaseConstant.LONG_ZERO;
                    //接收方邮件配置开关
                    String emailConfigKey = WalkRoomEmailConfig.generateKey(item.getToPropertyId(), WalkRoomApproveTypeEnum.RECEIVE.getCode());
                    Boolean emailConfigStatus = propertyIdAndType2EmailConfigStatus.getOrDefault(emailConfigKey, true);
                    return isNotStartApprove && emailConfigStatus;
                } else {
                    return false;
                }
            }).collect(Collectors.toList());

            if (CollectionUtils.isEmpty(sentNotStartApproveList) && CollectionUtils.isEmpty(receiveNotStartApproveList))
                return;

            //合并未开始审批的数据集合
            List<WalkRoomDateinOther> allNotStartApproveList = Lists.newArrayList(sentNotStartApproveList);
            allNotStartApproveList.addAll(receiveNotStartApproveList);
            //获取资产id集合
            Set<Integer> propertyIds = allNotStartApproveList.stream().flatMap(item -> Stream.of(item.getFromPropertyId(), item.getToPropertyId())).collect(Collectors.toSet());
            //获取walk room主键id集合
            Set<Long> reqIds = allNotStartApproveList.stream().map(WalkRoomDateinOther::getReqId).collect(toSet());
            //获取入住日集合(yyyyMMdd)
            Set<Integer> dates = allNotStartApproveList.stream().map(WalkRoomDateinOther::getDate).collect(toSet());

            //查询出资产配置的第一级审批层级
            Map<String, WalkRoomApproveLevel> propertyIdAndType2FirstApproveLevel = approveLevelService.listFirstApproveLevel(Lists.newArrayList(propertyIds));
            //审批人集合
            List<Long> allLevelIds = propertyIdAndType2FirstApproveLevel.values().stream().map(WalkRoomApproveLevel::getId).toList();
            Map<Long, List<Integer>> levelId2UserIds = approveConfigService.listByLevelIds(allLevelIds).stream().collect(groupingBy(WalkRoomApproveConfig::getLevelId,
                    mapping(WalkRoomApproveConfig::getUserId, toList())));

            //查询资产信息
            Map<Integer, PropertyDTO> propertyId2Property = propertyInternalService.getPropertyId2Property(propertyIds);

            //查询入住记录的rate集合
            Map<String, BigDecimal> reqIdAndDate2Rate = walkRoomDateinRateService.listReqIdAndDateMapByReqIdAndDate(reqIds, dates);

            //查询入住记录的walk room数据
            List<WalkRoomRequest> walkRoomRequests = walkRoomRequestService.listByIds(reqIds);

            //根据发送方资产id分组
            Map<Integer, List<WalkRoomDateinOther>> sentPropertyId2DateinOthers = sentNotStartApproveList.stream().collect(groupingBy(WalkRoomDateinOther::getFromPropertyId));
            sentPropertyId2DateinOthers.forEach((propertyId, dateinOthers) -> {
                WalkRoomApproveLevel firstApproveLevel = propertyIdAndType2FirstApproveLevel.get(
                        WalkRoomApproveLevel.generateKey(propertyId, WalkRoomApproveTypeEnum.SENT.getCode()));
                if (Objects.nonNull(firstApproveLevel)) {
                    List<Integer> userIdsByApproveLevel = levelId2UserIds.get(firstApproveLevel.getId());
                    //获取自定义主题
                    String emailConfigKey = WalkRoomEmailConfig.generateKey(propertyId, WalkRoomApproveTypeEnum.SENT.getCode());
                    String customSubejct = propertyIdAndType2EmailConfigSubject.getOrDefault(emailConfigKey, "");
                    //发送方的入住记录审批通知
                    sendDateinOtherApproveNotify(propertyId, dateinOthers, propertyId2Property,
                            walkRoomRequests, reqIdAndDate2Rate, WalkRoomApproveTypeEnum.SENT.getCode(),
                            userIdsByApproveLevel, firstApproveLevel.getCc(), customSubejct);
                }
            });

            //根据接收方资产id分组
            Map<Integer, List<WalkRoomDateinOther>> receivePropertyId2DateinOthers = receiveNotStartApproveList.stream().collect(groupingBy(WalkRoomDateinOther::getToPropertyId));
            receivePropertyId2DateinOthers.forEach((propertyId, dateinOthers) -> {
                WalkRoomApproveLevel firstApproveLevel = propertyIdAndType2FirstApproveLevel.get(
                        WalkRoomApproveLevel.generateKey(propertyId, WalkRoomApproveTypeEnum.RECEIVE.getCode()));
                if (Objects.nonNull(firstApproveLevel)) {
                    List<Integer> userIdsByApproveLevel = levelId2UserIds.get(firstApproveLevel.getId());
                    //获取自定义主题
                    String emailConfigKey = WalkRoomEmailConfig.generateKey(propertyId, WalkRoomApproveTypeEnum.RECEIVE.getCode());
                    String customSubejct = propertyIdAndType2EmailConfigSubject.getOrDefault(emailConfigKey, "");
                    //接收方的入住记录审批通知
                    sendDateinOtherApproveNotify(propertyId, dateinOthers, propertyId2Property,
                            walkRoomRequests, reqIdAndDate2Rate, WalkRoomApproveTypeEnum.RECEIVE.getCode(),
                            userIdsByApproveLevel, firstApproveLevel.getCc(), customSubejct);
                }
            });
        }

        /**
         * walk room数据变更后发送审批通知
         *
         * @param propertyId            资产id
         * @param walkRoomRequest       walk room数据
         * @param dateinOtherList       入住记录集合
         * @param propertyId2Property   资产集合
         * @param userId2Name           用户姓名集合
         * @param date2Rate             walk rate集合
         * @param approveType           审批类型1:sent 2:receive
         * @param userIdsByApproveLevel 审批人集合
         * @param cc                    抄送人集合
         * @param customSubject         自定义主题
         * @return void
         * @author lichen
         * @date 2023/7/22
         */
        private void sendWalkRoomApproveNotify(Integer propertyId, WalkRoomRequest walkRoomRequest, List<WalkRoomDateinOther> dateinOtherList,
                                               Map<Integer, PropertyDTO> propertyId2Property, Map<Integer, String> userId2Name,
                                               Map<Integer, BigDecimal> date2Rate, Integer approveType,
                                               List<Integer> userIdsByApproveLevel, @Nullable String cc, String customSubject) {
            //通知人集合
            List<NotifyIdentityDTO> allIdentityDTOList = Lists.newArrayListWithCapacity(userIdsByApproveLevel.size());
            allIdentityDTOList.addAll(userIdsByApproveLevel.stream()
                    .map(userId -> new NotifyIdentityDTO(EmailConfigCons.SOURCE_USER, userId, EmailConfigCons.TARGET_TYPE_TO, ""))
                    .toList());
            if (StringUtils.isNotBlank(cc) && !cc.equals("[]")) {
                List<NotifyIdentityDTO> identityDTOSByCC = JsonUtils.convertStringToList(objectMapper, cc, NotifyIdentityDTO.class);
                identityDTOSByCC.forEach(item -> item.setTargetType(EmailConfigCons.TARGET_TYPE_CC));
                allIdentityDTOList.addAll(identityDTOSByCC);
            }

            //发送方或接收方的资产DTO
            PropertyDTO propertyDTO = propertyId2Property.get(propertyId);

            //获取国际化配置
            String language = propertyDTO.getLanguage();
            String nameOrder = propertyDTO.getInternationalization().getNameOrder();
            InternationalizationNumberDTO number = propertyDTO.getInternationalization().getNumber();
            String calculationRule = number.getCalculationRule();
            String currency = number.getCurrency();

            //功能点
            FunctionPointEnum functionPointEnum = FunctionPointEnum.WALK_ROOM_REQUEST_SENDER_APPROVAL;
            if (approveType == WalkRoomApproveTypeEnum.RECEIVE.getCode()) {
                functionPointEnum = FunctionPointEnum.WALK_ROOM_REQUEST_RECEIVER_APPROVAL;
            }

            //WalkRoomRequest -> WalkRoomRequestNotifyVO
            WalkRoomNotifyVO walkRoomNotifyVO = convertWalkRoomRequestsToVO(walkRoomRequest, propertyId2Property, userId2Name, approveType);
            //List<WalkRoomDateinOther> -> List<WalkRoomDateinNotifyVO>
            List<WalkRoomDateinNotifyVO> dateinNotifyVOList = dateinOtherList.stream()
                    .map(dateinOther -> {
                        WalkRoomDateinNotifyVO walkRoomDateinNotifyVO = convertDateinOtherToVO(dateinOther, propertyId2Property, userId2Name, approveType);
                        BigDecimal rate = date2Rate.get(dateinOther.getDate());
                        walkRoomDateinNotifyVO.setRate(rate);
                        walkRoomDateinNotifyVO.setRateStr(InternationalizationUtils.formatAmountViewValue(rate, calculationRule, currency));
                        return walkRoomDateinNotifyVO;
                    }).collect(toList());

            //跳转链接
            String date = DateTimeUtils.dateNowStr(propertyDTO.getTimezone(), BaseConstant.DATE_FORMAT_YYYYMMDD);
            String linkUrl = MessageFormat.format(hereLink + "?property={0}&tenant={1}&activeKey={2}&queryDate={3}",
                    propertyDTO.getAbbr(), propertyDTO.getTenantSymbol(), approveType, date);
            String functionName = i18nMessageUtils.message(FunctionCons.WALK_ROOM_REQUESTS, language);

            //默认主题
            String defaultSubject = getDefaultSubject(propertyDTO, approveType);
            //主题
            String subject = StringUtils.isNotBlank(customSubject) ? customSubject : defaultSubject;

            //邮件通知内容
            Context context = new Context();
            context.setVariable("approveType", approveType);
            context.setVariable("dateinOtherVos", dateinNotifyVOList);
            context.setVariable("walkRoomVo", walkRoomNotifyVO);
            context.setVariable("hereLink", linkUrl);
            context.setVariable("propertyName", propertyDTO.getName());
            context.setVariable("functionName", functionName);
            String mailBody = templateEngine.process("walkroomrequest/walkRoomRequest-newOrEdit-approval_" + language, context);
            String emailContent = EmailUtil.getFullEmailContent(defaultSubject, mailBody, language);

            LinkedHashMap<String, String> businessMap = new LinkedHashMap<>();
            businessMap.put(i18nMessageUtils.message(WalkRoomFieldI18nConstant.I18N_GUEST_NAME, language),
                    InternationalizationUtils.formatName(walkRoomNotifyVO.getFirstName(), walkRoomNotifyVO.getLastName(), nameOrder));

            PublicFlexMsgParm publicFlexMsgParm = PublicFlexMsgParm.builder()
                    .propertyId(propertyDTO.getId())
                    .propertyName(propertyDTO.getName())
                    .functionName(functionName)
                    .title(getLineTitle(approveType))
                    .link(linkUrl)
                    .businessMap(businessMap)
                    .build();
            JSONObject textMsgJsonObject = lineMessageUtil.generatePublicFlexMsg(publicFlexMsgParm);

            //发送通知
            doSendNotify(propertyDTO, emailContent, textMsgJsonObject, functionPointEnum.getFunctionPoint(), allIdentityDTOList, subject);
        }

        /**
         * 发送入住记录的审批通知
         *
         * @param propertyId            资产id
         * @param dateinOthers          入住记录
         * @param propertyId2Property   资产集合
         * @param walkRoomRequests      walk room数据集合
         * @param reqIdAndDate2Rate     rate数据集合
         * @param approveType           审批类型
         * @param userIdsByApproveLevel 审批人
         * @param cc                    抄送人
         * @param customSubject         自定义主题
         * @return void
         * @author lichen
         * @date 2023/7/22
         */
        private void sendDateinOtherApproveNotify(Integer propertyId, List<WalkRoomDateinOther> dateinOthers,
                                                  Map<Integer, PropertyDTO> propertyId2Property, List<WalkRoomRequest> walkRoomRequests,
                                                  Map<String, BigDecimal> reqIdAndDate2Rate, Integer approveType,
                                                  List<Integer> userIdsByApproveLevel, @Nullable String cc, String customSubject) {
            Map<Long, WalkRoomRequest> reqId2WalkRoomRequest = walkRoomRequests.stream().collect(toMap(WalkRoomRequest::getId, Function.identity()));

            //过滤掉入住日等于离店日期的入住记录
            List<WalkRoomDateinOther> validDateinOthers = new ArrayList<>(dateinOthers.stream()
                    .filter(dateinOther -> {
                        WalkRoomRequest walkRoomRequest = reqId2WalkRoomRequest.get(dateinOther.getReqId());
                        return !dateinOther.getDate().equals(walkRoomRequest.getCheckOutDate());
                    }).toList());

            //按照日期倒序排序
            validDateinOthers.sort(Comparator.comparing(WalkRoomDateinOther::getDate).thenComparing(WalkRoomDateinOther::getId).reversed());

            //获取国际化配置
            PropertyDTO propertyDTO = propertyId2Property.get(propertyId);
            InternationalizationNumberDTO number = propertyDTO.getInternationalization().getNumber();
            String calculationRule = number.getCalculationRule();
            String currency = number.getCurrency();

            //获取租户id
            Integer tenantId = propertyId2Property.get(propertyId).getTenantId();

            //获取确认人集合
            List<Integer> updateBys = validDateinOthers.stream().map(WalkRoomDateinOther::getUpdateBy).toList();

            //获取入住记录对应的walk room数据的邮件发送人、前台联系人集合
            Set<Integer> sentBysAndAgentUserIds = walkRoomRequests.stream().flatMap(item -> Stream.of(item.getAgentUserId(), item.getLastSentBy())).collect(toSet());

            //合并所有的用户id集合
            Set<Integer> allUserIdSet = Sets.newHashSet();
            allUserIdSet.addAll(updateBys);
            allUserIdSet.addAll(sentBysAndAgentUserIds);
            //查询用户信息
            List<UserDTO> users = userInternalService.getUsers(tenantId, allUserIdSet);
            Map<Integer, String> userId2Name = users.stream().collect(Collectors.toMap(UserDTO::getId, UserDTO::getName));

            //入住记录集合转化为vo集合
            List<WalkRoomDateinNotifyVO> dateinOtherVOS = validDateinOthers.stream().map(dateinOther -> {
                //入住记录转化为vo
                WalkRoomDateinNotifyVO walkRoomDateinNotifyVO = convertDateinOtherToVO(dateinOther, propertyId2Property, userId2Name, approveType);
                //walk room数据转化为vo
                WalkRoomRequest walkRoomRequest = reqId2WalkRoomRequest.get(dateinOther.getReqId());
                WalkRoomNotifyVO walkRoomNotifyVO = convertWalkRoomRequestsToVO(walkRoomRequest, propertyId2Property, userId2Name, approveType);
                walkRoomDateinNotifyVO.setWalkRoomNotifyVO(walkRoomNotifyVO);
                //设置walk rate
                String rateKey = WalkRoomDateinRate.generateKey(dateinOther.getReqId(), dateinOther.getDate());
                BigDecimal rate = reqIdAndDate2Rate.get(rateKey);
                walkRoomDateinNotifyVO.setRate(rate);
                walkRoomDateinNotifyVO.setRateStr(InternationalizationUtils.formatAmountViewValue(rate, calculationRule, currency));
                return walkRoomDateinNotifyVO;
            }).collect(toList());

            //发送入住记录的审批通知
            sendDateinApproveNotify(dateinOtherVOS, approveType, propertyId2Property.get(propertyId), userIdsByApproveLevel, cc, customSubject);
        }

        /**
         * 把入住记录转化为VO
         *
         * @param walkRoomDateinOther    入住记录
         * @param propertyId2PropertyDTO 资产集合
         * @param userId2UserName        用户集合
         * @param approveType            审批类型1：sent 2:receive
         * @return cloud.wconnect.frontoffice.pojo.view.walkroom.notify.WalkRoomDateinNotifyVO
         * @author lichen
         * @date 2023/7/22
         */
        private WalkRoomDateinNotifyVO convertDateinOtherToVO(WalkRoomDateinOther walkRoomDateinOther,
                                                              Map<Integer, PropertyDTO> propertyId2PropertyDTO,
                                                              Map<Integer, String> userId2UserName, int approveType) {

            PropertyDTO i18nPropertyDTO = getI18nPropertyDTO(approveType, propertyId2PropertyDTO, walkRoomDateinOther.getFromPropertyId(), walkRoomDateinOther.getToPropertyId());
            //获取国际化配置
            String timezone = i18nPropertyDTO.getTimezone();
            String language = i18nPropertyDTO.getLanguage();
            InternationalizationDateTimeDTO dateTime = i18nPropertyDTO.getInternationalization().getDateTime();
            String longDate = dateTime.getLongDate();
            String hourClock = dateTime.getHourClock();

            //入住日期使用接收方的时区
            String timezoneByReceive = propertyId2PropertyDTO.get(walkRoomDateinOther.getToPropertyId()).getTimezone();

            return beanMapper.map(walkRoomDateinOther, WalkRoomDateinNotifyVO.class, vo -> {
                String dateStr = InternationalizationUtils.formatDateTime(
                        DateTimeUtils.dateStrToEpochSecond(walkRoomDateinOther.getDate().toString(), BaseConstant.DATE_FORMAT_YYYYMMDD, timezoneByReceive),
                        longDate, StringUtils.EMPTY, timezoneByReceive, language);
                vo.setDateStr(dateStr);
                //入住状态
                if (vo.getStatus() != 0) {
                    vo.setStatusDesc(i18nMessageUtils.message(WalkRoomStatusEnum.getI18nCode(vo.getStatus()), language));
                }
                //确认人
                vo.setUpdateByName(userId2UserName.get(vo.getUpdateBy()));
                //确认时间
                Long updateTime = vo.getUpdateTime();
                String updatedTimeStr = updateTime > 0
                        ? InternationalizationUtils.formatDateTime(updateTime, longDate, hourClock, timezone, language) : "";
                vo.setUpdateTimeStr(updatedTimeStr);
                //审批状态
                vo.setSentApproveStatusDesc(i18nMessageUtils.message(ApproveStatusEnum.getI18nCode(vo.getSentApproveStatus()), language));
                vo.setReceiveApproveStatusDesc(i18nMessageUtils.message(ApproveStatusEnum.getI18nCode(vo.getReceiveApproveStatus()), language));
                //跳转链接
                String linkUrl = MessageFormat.format(hereLink + "?property={0}&tenant={1}&activeKey={2}&queryDate={3}",
                        i18nPropertyDTO.getAbbr(), i18nPropertyDTO.getTenantSymbol(), approveType, walkRoomDateinOther.getDate().toString());
                vo.setHereLink(linkUrl);
            });
        }

        /**
         * 根据审批类型，资产DTO
         *
         * @param approveType            审批类型1：sent 2:receive
         * @param propertyId2PropertyDTO 资产DTO
         * @return void
         * @author lichen
         * @date 2024/1/19
         */
        private PropertyDTO getI18nPropertyDTO(int approveType, Map<Integer, PropertyDTO> propertyId2PropertyDTO,
                                               Integer fromPropertyId, Integer toPropertyId) {
            return WalkRoomApproveTypeEnum.SENT.getCode() == approveType ? propertyId2PropertyDTO.get(fromPropertyId)
                    : propertyId2PropertyDTO.get(toPropertyId);
        }

        /**
         * 把WalkRoomRequest转化成VO
         *
         * @param walkRoomRequest        walk room数据
         * @param propertyId2PropertyDTO 资产集合
         * @param userId2UserName        用户集合
         * @param approveType            审批类型1：sent 2:receive
         * @return cloud.wconnect.frontoffice.pojo.view.walkroom.notify.WalkRoomNotifyVO
         * @author lichen
         * @date 2023/7/22
         */
        private WalkRoomNotifyVO convertWalkRoomRequestsToVO(WalkRoomRequest walkRoomRequest,
                                                             Map<Integer, PropertyDTO> propertyId2PropertyDTO,
                                                             Map<Integer, String> userId2UserName, int approveType) {
            PropertyDTO i18nPropertyDTO = getI18nPropertyDTO(approveType, propertyId2PropertyDTO, walkRoomRequest.getFromPropertyId(), walkRoomRequest.getToPropertyId());
            //获取国际化配置
            String timezone = i18nPropertyDTO.getTimezone();
            String language = i18nPropertyDTO.getLanguage();
            InternationalizationDateTimeDTO dateTime = i18nPropertyDTO.getInternationalization().getDateTime();
            String longDate = dateTime.getLongDate();
            String hourClock = dateTime.getHourClock();
            String nameOrder = i18nPropertyDTO.getInternationalization().getNameOrder();

            //入住日期使用接收方的时区
            String timezoneByReceive = propertyId2PropertyDTO.get(walkRoomRequest.getToPropertyId()).getTimezone();

            return beanMapper.map(walkRoomRequest, WalkRoomNotifyVO.class, vo -> {
                PropertyDTO fromProperty = propertyId2PropertyDTO.get(walkRoomRequest.getFromPropertyId());
                PropertyDTO toProperty = propertyId2PropertyDTO.get(walkRoomRequest.getToPropertyId());
                vo.setFromPropertyName(fromProperty.getName());
                vo.setToPropertyName(toProperty.getName());
                //客人姓名国际化
                vo.setGuestName(InternationalizationUtils.formatName(walkRoomRequest.getFirstName(), walkRoomRequest.getLastName(), nameOrder));
                //入住日期
                vo.setCheckInDateStr(InternationalizationUtils.formatDateTime(
                        DateTimeUtils.dateStrToEpochSecond(walkRoomRequest.getCheckInDate().toString(), BaseConstant.DATE_FORMAT_YYYYMMDD, timezoneByReceive),
                        longDate, StringUtils.EMPTY, timezoneByReceive, language));
                //离店日期
                vo.setCheckOutDateStr(InternationalizationUtils.formatDateTime(
                        DateTimeUtils.dateStrToEpochSecond(walkRoomRequest.getCheckOutDate().toString(), BaseConstant.DATE_FORMAT_YYYYMMDD, timezoneByReceive),
                        longDate, StringUtils.EMPTY, timezoneByReceive, language));

                //邮件发送时间
                Long lastSentTime = walkRoomRequest.getLastSentTime();
                String lastSentTimeStr = lastSentTime > 0
                        ? InternationalizationUtils.formatDateTime(lastSentTime, longDate, hourClock, timezone, language) : "";
                vo.setLastSentTimeStr(lastSentTimeStr);
                //邮件发送人
                vo.setLastSentByName(userId2UserName.get(walkRoomRequest.getLastSentBy()));

                //设置发送方前台
                vo.setAgentUserName(userId2UserName.get(walkRoomRequest.getAgentUserId()));
            });
        }

        /**
         * 发送通知
         *
         * @param propertyDTO     发送方或接收方的资产DTO
         * @param emailContent    邮件内容
         * @param lineMsg         line消息内容
         * @param functionPoint   功能点
         * @param identityDTOList 通知对象集合
         * @param subject         通知主题
         * @return void
         * @author lichen
         * @date 2023/11/27
         */
        private void doSendNotify(PropertyDTO propertyDTO, String emailContent, JSONObject lineMsg,
                                  Integer functionPoint, List<NotifyIdentityDTO> identityDTOList, String subject) {
            NotifyDTO notifyDTO = new NotifyDTO();
            notifyDTO.setPropertyId(propertyDTO.getId());
            notifyDTO.setFunctionPoint(functionPoint);
            notifyDTO.setSubject(subject);
            notifyDTO.setIdentityList(identityDTOList);
            notifyDTO.setEmailContent(emailContent);
            notifyDTO.setLineContent(Lists.newArrayList(lineMsg));
            notifyInternalService.sendNotify(notifyDTO);
        }

        /**
         * 发送入住记录的审批通知
         *
         * @param dateinOtherVOS 入住记录集合
         * @param approveType    审批类型1：sent 2:receive
         * @param propertyDTO    资产DTO
         * @param approverIds    审批人ID集合
         * @param cc             抄送人数组
         * @param customSubject  自定义主题
         * @return void
         * @author lichen
         * @date 2023/11/27
         */
        private void sendDateinApproveNotify(List<WalkRoomDateinNotifyVO> dateinOtherVOS, Integer approveType,
                                             PropertyDTO propertyDTO, List<Integer> approverIds, @Nullable String cc, String customSubject) {
            //通知人集合
            List<NotifyIdentityDTO> allIdentityDTOList = Lists.newArrayListWithCapacity(approverIds.size());
            allIdentityDTOList.addAll(approverIds.stream()
                    .map(userId -> new NotifyIdentityDTO(EmailConfigCons.SOURCE_USER, userId, EmailConfigCons.TARGET_TYPE_TO, ""))
                    .toList());
            if (StringUtils.isNotBlank(cc) && !cc.equals("[]")) {
                List<NotifyIdentityDTO> identityDTOSByCC = JsonUtils.convertStringToList(objectMapper, cc, NotifyIdentityDTO.class);
                identityDTOSByCC.forEach(item -> item.setTargetType(EmailConfigCons.TARGET_TYPE_CC));
                allIdentityDTOList.addAll(identityDTOSByCC);
            }

            String language = propertyDTO.getLanguage();

            //功能点
            FunctionPointEnum functionPointEnum = FunctionPointEnum.WALK_ROOM_REQUEST_SENDER_APPROVAL;
            if (approveType == WalkRoomApproveTypeEnum.RECEIVE.getCode()) {
                functionPointEnum = FunctionPointEnum.WALK_ROOM_REQUEST_RECEIVER_APPROVAL;
            }

            //跳转链接
            String currentDate = DateTimeUtils.dateNowStr(propertyDTO.getTimezone(), BaseConstant.DATE_FORMAT_YYYYMMDD);
            String linkUrl = MessageFormat.format(hereLink + "?property={0}&tenant={1}&activeKey={2}&queryDate={3}",
                    propertyDTO.getAbbr(), propertyDTO.getTenantSymbol(), approveType, currentDate);
            //功能名称
            String functionName = i18nMessageUtils.message(FunctionCons.WALK_ROOM_REQUESTS, language);
            //获取默认主题
            String defaultSubject = getDefaultSubject(propertyDTO, approveType);
            //主题
            String subject = StringUtils.isNotBlank(customSubject) ? customSubject : defaultSubject;
            //邮件内容
            Context context = new Context();
            context.setVariable("approveType", approveType);
            context.setVariable("dateinOthers", dateinOtherVOS);
            context.setVariable("hereLink", linkUrl);
            context.setVariable("propertyName", propertyDTO.getName());
            context.setVariable("functionName", functionName);
            String mailBody = templateEngine.process("walkroomrequest/walkRoomRequest-checkInRecords-approval_" + language, context);
            String emailContent = EmailUtil.getFullEmailContent(defaultSubject, mailBody, language);

            LinkedHashMap<String, String> businessMap = new LinkedHashMap<>();
            Set<String> dateStrList = dateinOtherVOS.stream().map(WalkRoomDateinNotifyVO::getDateStr).collect(toSet());
            businessMap.put(i18nMessageUtils.message(WalkRoomFieldI18nConstant.I18N_CHECK_IN_DATE, language),
                    StringUtils.join(dateStrList, " ; "));

            PublicFlexMsgParm publicFlexMsgParm = PublicFlexMsgParm.builder()
                    .propertyId(propertyDTO.getId())
                    .propertyName(propertyDTO.getName())
                    .functionName(functionName)
                    .title(getLineTitle(approveType))
                    .link(linkUrl)
                    .businessMap(businessMap)
                    .build();
            //根据通知内容生成文本消息
            JSONObject textMsgJsonObject = lineMessageUtil.generatePublicFlexMsg(publicFlexMsgParm);
            //发送通知
            doSendNotify(propertyDTO, emailContent, textMsgJsonObject, functionPointEnum.getFunctionPoint(), allIdentityDTOList, subject);
        }

        /**
         * 获取line通知的title
         *
         * @param approveType 审批类型
         * @return java.lang.String
         * @author lichen
         * @date 2024/11/14
         */
        private String getLineTitle(Integer approveType) {
            if (approveType == WalkRoomApproveTypeEnum.RECEIVE.getCode()) {
                return "Waiting for approval of receiver";
            } else {
                return "Waiting for approval of sender";
            }
        }

        /**
         * 获取默认的通知主题
         *
         * @param propertyDTO 资产DTO
         * @param notifyType  通知类型
         * @return java.lang.String
         * @author lichen
         * @date 2025/1/16
         */
        private String getDefaultSubject(PropertyDTO propertyDTO, Integer notifyType) {
            //功能名称
            String functionName = i18nMessageUtils.message(FunctionCons.WALK_ROOM_REQUESTS, propertyDTO.getLanguage());
            //默认主题
            String defaultSubjectI18nCode = WalkRoomRequestNotifyConfigTypeEnum.getDefaultSubjectI18nCode(notifyType);
            return i18nMessageUtils.message(defaultSubjectI18nCode, propertyDTO.getLanguage(), functionName, propertyDTO.getName());
        }
    }