# WalkRoomRequestServiceImpl.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.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.FunctionCons;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    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.line.PublicFlexMsgParm;
    import cloud.wconnect.commonlib.redis.PropertyI18nRedisService;
    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.FunctionPointEnum;
    import cloud.wconnect.frontoffice.cons.walkroomrequest.WalkRoomFieldI18nConstant;
    import cloud.wconnect.frontoffice.cons.walkroomrequest.WalkRoomErrorI18nConstant;
    import cloud.wconnect.frontoffice.cons.walkroomrequest.WalkRoomRequestNotifyConfigTypeEnum;
    import cloud.wconnect.frontoffice.entity.walkroomrequest.*;
    import cloud.wconnect.frontoffice.mapper.walkroomrequest.WalkRoomRequestMapper;
    import cloud.wconnect.frontoffice.pojo.dto.walkroomrequest.WalkRoomRequestDTO;
    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.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.google.common.collect.ImmutableMap;
    import com.google.common.collect.Lists;
    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.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    import org.thymeleaf.TemplateEngine;
    import org.thymeleaf.context.Context;

    import java.text.MessageFormat;
    import java.time.LocalDate;
    import java.time.ZoneId;
    import java.util.*;
    import java.util.concurrent.Executor;

    /**
     * <p>
     * Walk Room Requests 服务实现类
     * </p>
     *
     * @author lichen
     * @since 2023-07-08
     */
    @Service
    @DS("logbook")
    public class WalkRoomRequestServiceImpl extends ServiceImpl<WalkRoomRequestMapper, WalkRoomRequest> implements IWalkRoomRequestService {

        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private IWalkRoomRequestLogService walkRoomRequestLogService;
        @Autowired
        private IWalkRoomRateService walkRoomRateService;
        @Autowired
        private IWalkRoomDateinRateService walkRoomDateinRateService;
        @Autowired
        private IWalkRoomDateinOtherService walkRoomDateinOtherService;
        @Autowired
        @Lazy
        private IWalkRoomNotifyService walkRoomNotifyServiceImpl;
        @Autowired
        private Executor executor;
        @Autowired
        private IWalkRoomEmailConfigService emailConfigService;
        @Autowired
        private PropertyInternalService propertyInternalService;
        @Autowired
        private UserInternalService userInternalService;
        @Autowired
        private TemplateEngine templateEngine;
        @Autowired
        private NotifyInternalService notifyInternalService;
        @Autowired
        private LineMessageUtil lineMessageUtil;
        @Autowired
        private I18nMessageUtils i18nMessageUtils;
        @Value("${here.link.walk-room-requests}")
        private String hereLink;
        @Autowired
        private IWalkRoomEmailTargetService emailTargetService;
        @Autowired
        private PropertyI18nRedisService propertyI18nRedisService;
        @Autowired
        private IWalkRoomApproveLogService approveLogService;

        /**
         * 保存walk room
         *
         * @param walkRoomRequestDTO       walk room数据
         * @param propertyIdAndType2Levels 发送方和接收方的审批层级集合
         * @return java.util.Map
         * @author lichen
         * @date 2023/7/18
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public Map save(WalkRoomRequestDTO walkRoomRequestDTO, Map<String, List<WalkRoomApproveLevel>> propertyIdAndType2Levels, int loginUserId) {
            WalkRoomRequest walkRoomRequest = beanMapper.map(walkRoomRequestDTO, WalkRoomRequest.class, entity -> {
                entity.setCreatedBy(loginUserId);
                entity.setCreatedTime(DateTimeUtils.nowTimestamp());
                entity.setLastSentBy(0);
                entity.setLastSentTime(0L);
            });
            //新增walkRoom
            save(walkRoomRequest);

            //检查checkInDate是否有To Property统一设置的rate值，如果有则设置 rate 值
            WalkRoomRate walkRoomRate = walkRoomRateService.getByPropertyIdAndDate(walkRoomRequestDTO.getToPropertyId(), walkRoomRequest.getCheckInDate());
            if (walkRoomRate != null) {
                //设置checkInDate的rate值
                WalkRoomDateinRate walkRoomDateinRate = new WalkRoomDateinRate();
                walkRoomDateinRate.setFromPropertyId(walkRoomRequest.getFromPropertyId());
                walkRoomDateinRate.setToPropertyId(walkRoomRequest.getToPropertyId());
                walkRoomDateinRate.setDate(walkRoomRequest.getCheckInDate());
                walkRoomDateinRate.setRate(walkRoomRate.getRoomRate());
                walkRoomDateinRate.setReqId(walkRoomRequest.getId());
                walkRoomDateinRate.setUpdateBy(loginUserId);
                walkRoomDateinRate.setUpdateTime(DateTimeUtils.nowTimestamp());
                walkRoomDateinRateService.save(walkRoomDateinRate);
            }

            Integer checkInDate = walkRoomRequest.getCheckInDate();
            Integer checkOutDate = walkRoomRequest.getCheckOutDate();
            //如果用户入住天数不是 1 天，保存checkInDate的入住记录
            if (!checkInDate.equals(checkOutDate)) {
                //接收方资产时区
                String timezoneByToPropertyId = propertyI18nRedisService.get(walkRoomRequest.getToPropertyId()).getTimezone();
                LocalDate currentDate = LocalDate.now(ZoneId.of(timezoneByToPropertyId));
                //入住日期
                LocalDate localDateByCheckInDate = DateTimeUtils.strToLocalDate(checkInDate.toString(), BaseConstant.DATE_FORMAT_YYYYMMDD);
                //入住日期在当前日期之前
                if (localDateByCheckInDate.isBefore(currentDate)) {
                    //循环保存当前日期之前的入住记录
                    for (LocalDate localDate = localDateByCheckInDate; !localDate.isAfter(currentDate); localDate = localDate.plusDays(1)) {
                        walkRoomDateinOtherService.saveDateinOther(walkRoomRequest,
                                Integer.valueOf(DateTimeUtils.localDateToStr(localDate, BaseConstant.DATE_FORMAT_YYYYMMDD)),
                                propertyIdAndType2Levels);
                    }
                } else {
                    //保存入住记录
                    walkRoomDateinOtherService.saveDateinOther(walkRoomRequest, checkInDate, propertyIdAndType2Levels);
                }
                //发送审批通知
                TransactionUtils.afterCommitAsyncExecute(executor, () -> walkRoomNotifyServiceImpl.walkRoomChangeSendApproveNotify(walkRoomRequest.getId()));
            }
            //保存新增walkRoom的日志
            walkRoomRequestLogService.saveLogForInsert(walkRoomRequest, loginUserId);
            return ImmutableMap.of("id", walkRoomRequest.getId());
        }

        /**
         * 修改walk room
         *
         * @param walkRoomRequestDTO       修改后的walk room dto
         * @param propertyIdAndType2Levels 发送方和接收方的审批层级集合
         * @param loginUserId              登录用户id
         * @return void
         * @author lichen
         * @date 2023/7/18
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void update(WalkRoomRequestDTO walkRoomRequestDTO, Map<String, List<WalkRoomApproveLevel>> propertyIdAndType2Levels, int loginUserId) {
            WalkRoomRequest updateWalkRoomRequest = beanMapper.map(walkRoomRequestDTO, WalkRoomRequest.class, entity -> {
                entity.setUpdatedBy(loginUserId);
                entity.setUpdatedTime(DateTimeUtils.nowTimestamp());
            });
            //修改walk room数据
            updateById(updateWalkRoomRequest);

            //重置walk room所有入住记录的审批信息
            walkRoomDateinOtherService.resetAllDateinApproveInfoAndConfirm(updateWalkRoomRequest, propertyIdAndType2Levels, false);

            Integer checkInDate = walkRoomRequestDTO.getCheckInDate();
            Integer checkOutDate = walkRoomRequestDTO.getCheckOutDate();
            if (checkInDate.equals(checkOutDate)) {//如果用户入住天数是1天
                //删除所有的入住记录
                walkRoomDateinOtherService.removeByReqId(walkRoomRequestDTO.getId());
                //删除所有的walk rate明细
                walkRoomDateinRateService.removeByReqId(walkRoomRequestDTO.getId());
                //清空 final other id
                WalkRoomRequest clearFinalOtherIdAndCrsNumber = new WalkRoomRequest();
                clearFinalOtherIdAndCrsNumber.setId(walkRoomRequestDTO.getId());
                clearFinalOtherIdAndCrsNumber.setFinalOtherId(0L);
                clearFinalOtherIdAndCrsNumber.setFinalCrsNumber("");
                updateById(clearFinalOtherIdAndCrsNumber);
            } else {
                //接收方资产时区
                String timezoneByToPropertyId = propertyI18nRedisService.get(walkRoomRequestDTO.getToPropertyId()).getTimezone();
                LocalDate currentDate = LocalDate.now(ZoneId.of(timezoneByToPropertyId));
                //入住日期
                LocalDate localDateByCheckInDate = DateTimeUtils.strToLocalDate(checkInDate.toString(), BaseConstant.DATE_FORMAT_YYYYMMDD);
                //入住日期在当前日期之前
                if (localDateByCheckInDate.isBefore(currentDate)) {
                    //循环保存当前日期之前的入住记录
                    for (LocalDate localDate = localDateByCheckInDate; !localDate.isAfter(currentDate); localDate = localDate.plusDays(1)) {
                        walkRoomDateinOtherService.saveDateinOther(updateWalkRoomRequest,
                                Integer.valueOf(DateTimeUtils.localDateToStr(localDate, BaseConstant.DATE_FORMAT_YYYYMMDD)),
                                propertyIdAndType2Levels);
                    }
                } else {
                    //保存入住记录
                    walkRoomDateinOtherService.saveDateinOther(updateWalkRoomRequest, checkInDate, propertyIdAndType2Levels);
                }
                /**
                 * 用户可能修改checkInDate 、checkOutDate，所以需要删除掉入住日期范围之外的入住记录和walk rate
                 */
                walkRoomDateinOtherService.removeByReqIdAndDateRange(walkRoomRequestDTO.getId(), checkInDate, checkOutDate, false);
                walkRoomDateinRateService.removeByReqIdAndDateRange(walkRoomRequestDTO.getId(), checkInDate, checkOutDate, false);
                //发送审批通知
                TransactionUtils.afterCommitAsyncExecute(executor, () -> walkRoomNotifyServiceImpl.walkRoomChangeSendApproveNotify(updateWalkRoomRequest.getId()));
            }
            //保存修改的walkRoom的日志
            walkRoomRequestLogService.saveLogForUpdate(updateWalkRoomRequest.getId(), loginUserId);
        }

        /**
         * 修改walk room接收方
         *
         * @param walkRoomRequestDTO       修改后的walk room dto
         * @param propertyIdAndType2Levels 发送方和接收方的审批层级集合
         * @param loginUserId              登录用户id
         * @return void
         * @author lichen
         * @date 2023/7/18
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void updateReceiver(WalkRoomRequestDTO walkRoomRequestDTO, Map<String, List<WalkRoomApproveLevel>> propertyIdAndType2Levels, int loginUserId) {
            WalkRoomRequest updateWalkRoomRequest = beanMapper.map(walkRoomRequestDTO, WalkRoomRequest.class, entity -> {
                entity.setUpdatedBy(loginUserId);
                entity.setUpdatedTime(DateTimeUtils.nowTimestamp());
                //接收方的确认信息都需要重置，所以失效日也需要重置为0
                entity.setInvalidDate(0);
            });
            //修改walk room数据
            updateById(updateWalkRoomRequest);

            /**
             * 1. 重置walk room所有入住记录的审批信息
             * 2. 重置walk room所有入住记录接收方的确认信息
             * 3. 修改接收方
             */
            walkRoomDateinOtherService.resetAllDateinApproveInfoAndConfirm(updateWalkRoomRequest, propertyIdAndType2Levels, true);

            //修改walk rate记录的接收方
            walkRoomDateinRateService.updateReceiverByReqId(walkRoomRequestDTO.getId(), walkRoomRequestDTO.getToPropertyId(), loginUserId);

            Integer checkInDate = walkRoomRequestDTO.getCheckInDate();
            Integer checkOutDate = walkRoomRequestDTO.getCheckOutDate();
            if (checkInDate.equals(checkOutDate)) {
                //删除所有的入住记录
                walkRoomDateinOtherService.removeByReqId(walkRoomRequestDTO.getId());
                //删除所有的walk rate明细
                walkRoomDateinRateService.removeByReqId(walkRoomRequestDTO.getId());
                //清空 final other id
                WalkRoomRequest clearFinalOtherIdAndCrsNumber = new WalkRoomRequest();
                clearFinalOtherIdAndCrsNumber.setId(walkRoomRequestDTO.getId());
                clearFinalOtherIdAndCrsNumber.setFinalOtherId(0L);
                clearFinalOtherIdAndCrsNumber.setFinalCrsNumber("");
                updateById(clearFinalOtherIdAndCrsNumber);
            } else {
                //接收方资产时区
                String timezoneByToPropertyId = propertyI18nRedisService.get(updateWalkRoomRequest.getToPropertyId()).getTimezone();
                LocalDate currentDate = LocalDate.now(ZoneId.of(timezoneByToPropertyId));
                //入住日期
                LocalDate localDateByCheckInDate = DateTimeUtils.strToLocalDate(checkInDate.toString(), BaseConstant.DATE_FORMAT_YYYYMMDD);
                //入住日期在当前日期之前
                if (localDateByCheckInDate.isBefore(currentDate)) {
                    //循环保存当前日期之前的入住记录
                    for (LocalDate localDate = localDateByCheckInDate; !localDate.isAfter(currentDate); localDate = localDate.plusDays(1)) {
                        walkRoomDateinOtherService.saveDateinOther(updateWalkRoomRequest,
                                Integer.valueOf(DateTimeUtils.localDateToStr(localDate, BaseConstant.DATE_FORMAT_YYYYMMDD)),
                                propertyIdAndType2Levels);
                    }
                } else {
                    //保存入住记录
                    walkRoomDateinOtherService.saveDateinOther(updateWalkRoomRequest, checkInDate, propertyIdAndType2Levels);
                }
                /**
                 * 用户可能修改checkInDate 、checkOutDate，所以需要删除掉入住日期范围之外的入住记录和walk rate
                 */
                walkRoomDateinOtherService.removeByReqIdAndDateRange(walkRoomRequestDTO.getId(), checkInDate, checkOutDate, false);
                walkRoomDateinRateService.removeByReqIdAndDateRange(walkRoomRequestDTO.getId(), checkInDate, checkOutDate, false);
                //发送审批通知
                TransactionUtils.afterCommitAsyncExecute(executor, () -> walkRoomNotifyServiceImpl.walkRoomChangeSendApproveNotify(updateWalkRoomRequest.getId()));
            }

            //保存修改的walkRoom的日志
            walkRoomRequestLogService.saveLogForUpdate(updateWalkRoomRequest.getId(), loginUserId);
        }

        /**
         * 更新finalOtherId、finalCrsNumber字段
         *
         * @param oriWalkRoomRequest 更新前的walk room数据
         * @return void
         * @author lichen
         * @date 2023/7/13
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void updateFinalOtherIdAndFinalCrsNumber(WalkRoomRequest oriWalkRoomRequest) {
            //判断客人是否提前退房，如果客人提前退房则不用更新finalOtherId和finalCrsNumber
            if (oriWalkRoomRequest.getInvalidDate() != null && oriWalkRoomRequest.getInvalidDate() != 0) {
                return;
            }
            //根据walk room主键id查询入住记录
            List<WalkRoomDateinOther> walkRoomDateinOthers = walkRoomDateinOtherService.listByReqIds(Collections.singletonList(oriWalkRoomRequest.getId()));
            if (CollectionUtils.isEmpty(walkRoomDateinOthers)) return;

            //把入住记录按照入住日倒序排列
            walkRoomDateinOthers.sort(Comparator.comparing(WalkRoomDateinOther::getDate).reversed());

            //构建更新的对象
            WalkRoomRequest updateRequest = new WalkRoomRequest();
            updateRequest.setId(oriWalkRoomRequest.getId());
            updateRequest.setFinalOtherId(walkRoomDateinOthers.get(0).getId());
            updateRequest.setFinalCrsNumber(walkRoomDateinOthers.get(0).getCrsNumber());
            updateById(updateRequest);
        }

        /**
         * 给接收方资产发送通知
         *
         * @param walkRoomRequest walk room数据
         * @param loginUserId     登录用户id
         * @param username        用户姓名
         * @return void
         * @author lichen
         * @date 2023/7/18
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void sendNotifyToReceiver(WalkRoomRequest walkRoomRequest, int loginUserId, String username) {
            //查询资产集合
            Map<Integer, PropertyDTO> propertyId2PropertyDTO = propertyInternalService.getPropertyId2Property(Arrays.asList(walkRoomRequest.getFromPropertyId(), walkRoomRequest.getToPropertyId()));

            //发送方资产
            Integer fromPropertyId = walkRoomRequest.getFromPropertyId();
            PropertyDTO fromPropertyDTO = propertyId2PropertyDTO.get(fromPropertyId);

            //接收方资产
            Integer toPropertyId = walkRoomRequest.getToPropertyId();
            PropertyDTO toPropertyDTO = propertyId2PropertyDTO.get(toPropertyId);

            //查询接收方的邮件配置
            WalkRoomEmailConfig emailConfig = emailConfigService.getByPropertyIdAndType(toPropertyId, WalkRoomRequestNotifyConfigTypeEnum.SAVE.getType());
            if (Objects.isNull(emailConfig)) {
                throw new BadRequestException(WalkRoomErrorI18nConstant.NOT_CONFIG_NOTIFY_CONFIG,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "The walk room request email configuration is not configured");
            }
            if (!emailConfig.getStatus()) {
                throw new BadRequestException(WalkRoomErrorI18nConstant.NOTIFY_CONFIG_OFF,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "The mail configuration state is off, unable to send mail to the target user");
            }
            List<WalkRoomEmailTarget> emailTargets = emailTargetService.listByConfigId(Lists.newArrayList(emailConfig.getId()));
            if (CollectionUtils.isEmpty(emailTargets)) {
                throw new BadRequestException(WalkRoomErrorI18nConstant.NOT_CONFIG_NOTIFY_CONFIG,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "The walk room request email configuration is not configured");
            }

            long lastSendTime = DateTimeUtils.dateTimeNowOfSecond(fromPropertyDTO.getTimezone());
            //更新发送人和发送时间
            WalkRoomRequest updateEntity = new WalkRoomRequest();
            updateEntity.setLastSentBy(loginUserId);
            updateEntity.setLastSentTime(lastSendTime);
            updateEntity.setId(walkRoomRequest.getId());
            updateById(updateEntity);

            //接收方前台联系人姓名
            UserDTO agentUserDTO = userInternalService.getOne(toPropertyDTO.getTenantId(), walkRoomRequest.getAgentUserId());
            String agentUserName = Objects.nonNull(agentUserDTO) ? agentUserDTO.getName() : "";

            //获取接收方的国际化配置
            String nameOrder = toPropertyDTO.getInternationalization().getNameOrder();
            InternationalizationDateTimeDTO dateTime = toPropertyDTO.getInternationalization().getDateTime();
            String longDate = dateTime.getLongDate();
            String hourClock = dateTime.getHourClock();

            String timezone = toPropertyDTO.getTimezone();
            String language = toPropertyDTO.getLanguage();

            //WalkRoomRequest -> WalkRoomForSaveVO
            WalkRoomNotifyVO walkRoomNotifyVO = beanMapper.map(walkRoomRequest, WalkRoomNotifyVO.class, vo -> {
                //设置客人姓名
                vo.setGuestName(InternationalizationUtils.formatName(walkRoomRequest.getFirstName(), walkRoomRequest.getLastName(), nameOrder));
                //设置发送方资产名称
                vo.setFromPropertyName(fromPropertyDTO.getName());
                //设置接收方资产名称
                vo.setToPropertyName(toPropertyDTO.getName());
                //设置checkInDate
                long checkInDateLong = DateTimeUtils.dateStrToEpochSecond(walkRoomRequest.getCheckInDate().toString(), BaseConstant.DATE_FORMAT_YYYYMMDD, timezone);
                vo.setCheckInDateStr(InternationalizationUtils.formatDateTime(checkInDateLong,
                        longDate, StringUtils.EMPTY, timezone, language));
                //设置checkOutDate
                long checkOutDateLong = DateTimeUtils.dateStrToEpochSecond(walkRoomRequest.getCheckOutDate().toString(), BaseConstant.DATE_FORMAT_YYYYMMDD, timezone);
                vo.setCheckOutDateStr(InternationalizationUtils.formatDateTime(checkOutDateLong,
                        longDate, StringUtils.EMPTY, timezone, language));
                //设置发送方前台人员姓名
                vo.setAgentUserName(agentUserName);
                //设置邮件发送人姓名
                vo.setLastSentByName(username);
                //设置发送时间
                vo.setLastSentTimeStr(InternationalizationUtils.formatDateTime(lastSendTime, longDate, hourClock, timezone, language));
            });
            //发送通知
            doSendNotify(toPropertyDTO, fromPropertyDTO, emailConfig, emailTargets, walkRoomNotifyVO);
        }

        /**
         * 删除walk room request数据
         *
         * @param walkRoomRequest walk room request数据
         * @return void
         * @author lichen
         * @date 2024/6/25
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void remove(WalkRoomRequest walkRoomRequest) {
            removeById(walkRoomRequest);

            //查询入住记录
            List<Long> dateinOtherIds = walkRoomDateinOtherService.listByReqIds(Collections.singletonList(walkRoomRequest.getId()))
                    .stream().map(WalkRoomDateinOther::getId).toList();
            if (CollectionUtils.isNotEmpty(dateinOtherIds)) {
                //删除审批日志
                approveLogService.remove(new LambdaQueryWrapper<WalkRoomApproveLog>()
                        .in(WalkRoomApproveLog::getDateinOtherId, dateinOtherIds)
                        .eq(WalkRoomApproveLog::getReqId, walkRoomRequest.getId()));
                //删除入住记录数据
                walkRoomDateinOtherService.removeByIds(dateinOtherIds);
            }
            //删除rate
            walkRoomDateinRateService.remove(new LambdaQueryWrapper<WalkRoomDateinRate>()
                    .eq(WalkRoomDateinRate::getReqId, walkRoomRequest.getId()));
            //删除操作日志
            walkRoomRequestLogService.remove(new LambdaQueryWrapper<WalkRoomRequestLog>()
                    .eq(WalkRoomRequestLog::getWalkRoomReqId, walkRoomRequest.getId()));
        }

        /**
         * 发送通知
         *
         * @param toPropertyDTO    接收方资产DTO
         * @param fromPropertyDTO  发送方资产DTO
         * @param emailConfig      通知配置
         * @param emailTargets     通知对象集合
         * @param walkRoomNotifyVO walk room request数据
         * @return void
         * @author lichen
         * @date 2023/11/22
         */
        private void doSendNotify(PropertyDTO toPropertyDTO, PropertyDTO fromPropertyDTO, WalkRoomEmailConfig emailConfig,
                                  List<WalkRoomEmailTarget> emailTargets, WalkRoomNotifyVO walkRoomNotifyVO) {
            String language = toPropertyDTO.getLanguage();
            //功能名称
            String functionName = i18nMessageUtils.message(FunctionCons.WALK_ROOM_REQUESTS, language);
            //拼装hereLink
            String linkUrl = MessageFormat.format(hereLink + "?property={0}&tenant={1}&activeKey=3&page=1&size=10&type=2&guestName={2}",
                    toPropertyDTO.getAbbr(), toPropertyDTO.getTenantSymbol(), walkRoomNotifyVO.getFirstName());

            //默认主题的国际化code
            String defaultSubjectI18nCode = WalkRoomRequestNotifyConfigTypeEnum.getDefaultSubjectI18nCode(emailConfig.getType());
            String defaultSubject = i18nMessageUtils.message(defaultSubjectI18nCode, language, functionName, toPropertyDTO.getName());
            //自定义主体优先，其次默认主题
            String subject = StringUtils.isNotBlank(emailConfig.getSubject()) ? emailConfig.getSubject() : defaultSubject;

            //邮件内容
            Context context = new Context();
            context.setVariable("propertyName", toPropertyDTO.getName());
            context.setVariable("functionName", functionName);
            context.setVariable("walkRoomVo", walkRoomNotifyVO);
            context.setVariable("hereLink", linkUrl);
            String mailBody = templateEngine.process("walkroomrequest/walkRoomRequest-newOrEdit_" + language, context);
            String emailContent = EmailUtil.getFullEmailContent(defaultSubject, mailBody, language);

            //line内容
            LinkedHashMap<String, String> businessMap = new LinkedHashMap<>();
            businessMap.put(i18nMessageUtils.message(WalkRoomFieldI18nConstant.I18N_SEND_PROPERTY, language), fromPropertyDTO.getName());
            businessMap.put(i18nMessageUtils.message(WalkRoomFieldI18nConstant.I18N_GUEST_NAME, language), walkRoomNotifyVO.getGuestName());
            businessMap.put(i18nMessageUtils.message(WalkRoomFieldI18nConstant.I18N_CHECK_IN_DATE, language), walkRoomNotifyVO.getCheckInDateStr());
            businessMap.put(i18nMessageUtils.message(WalkRoomFieldI18nConstant.I18N_CHECK_OUT_DATE, language), walkRoomNotifyVO.getCheckOutDateStr());

            PublicFlexMsgParm publicFlexMsgParm = PublicFlexMsgParm.builder()
                    .propertyId(toPropertyDTO.getId())
                    .propertyName(toPropertyDTO.getName())
                    .functionName(functionName)
                    .title("Receive New/Edit walk room request")
                    .link(linkUrl)
                    .businessMap(businessMap)
                    .build();
            JSONObject textMsgJsonObject = lineMessageUtil.generatePublicFlexMsg(publicFlexMsgParm);

            NotifyDTO notifyDTO = new NotifyDTO();
            notifyDTO.setPropertyId(toPropertyDTO.getId());
            notifyDTO.setFunctionPoint(FunctionPointEnum.WALK_ROOM_REQUEST_NOTIFY_RECEIVER.getFunctionPoint());
            notifyDTO.setSubject(subject);
            notifyDTO.setIdentityList(beanMapper.mapList(emailTargets, NotifyIdentityDTO.class));

            //设置邮件内容
            notifyDTO.setEmailContent(emailContent);
            //设置line通知内容
            notifyDTO.setLineContent(Lists.newArrayList(textMsgJsonObject));
            //发送通知
            notifyInternalService.sendNotify(notifyDTO);
        }

    }