# NotifyCompRoomTask.java

    package cloud.wconnect.frontoffice.businesstask.comproom;

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.BaseConstant;
    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.internationalization.InternationalizationDateTimeDTO;
    import cloud.wconnect.commonlib.pojo.dto.line.PublicFlexMsgParm;
    import cloud.wconnect.commonlib.redis.PropertyI18nRedisService;
    import cloud.wconnect.commonlib.service.MailInternalService;
    import cloud.wconnect.commonlib.service.NotifyInternalService;
    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.I18nConstant;
    import cloud.wconnect.frontoffice.cons.comproom.CompRoomNotifyConfigTypeEnum;
    import cloud.wconnect.frontoffice.entity.comproom.CompRoomEmailConfig;
    import cloud.wconnect.frontoffice.entity.comproom.CompRoomEmailTarget;
    import cloud.wconnect.frontoffice.entity.comproom.CompRoomScheduler;
    import cloud.wconnect.frontoffice.entity.comproom.RqCompRoomForm;
    import cloud.wconnect.frontoffice.pojo.vo.comproom.CompRoomEmailVO;
    import cloud.wconnect.frontoffice.service.comproom.ICompRoomEmailConfigService;
    import cloud.wconnect.frontoffice.service.comproom.ICompRoomEmailTargetService;
    import cloud.wconnect.frontoffice.service.comproom.IRqCompRoomFormService;
    import com.alibaba.fastjson.JSONObject;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.google.common.collect.Lists;
    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.scheduling.annotation.Async;
    import org.springframework.stereotype.Component;
    import org.thymeleaf.TemplateEngine;
    import org.thymeleaf.context.Context;

    import java.text.MessageFormat;
    import java.util.LinkedHashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Objects;
    import java.util.stream.Collectors;

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

    /**
     * lichen 每天邮件通知Guests In-House Complimentary报告中的免费房数据
     *
     * @author lichen
     * @date 2023/8/7
     */
    @Slf4j
    @Component
    public class NotifyCompRoomTask {

        @Autowired
        private PropertyI18nRedisService propertyI18nRedisService;
        @Autowired
        private TemplateEngine templateEngine;
        @Autowired
        private ICompRoomEmailConfigService compRoomEmailConfigService;
        @Autowired
        private IRqCompRoomFormService compRoomFormService;
        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private ObjectMapper objectMapper;
        @Autowired
        private UserInternalService userInternalService;
        @Autowired
        private NotifyInternalService notifyInternalService;
        @Autowired
        private LineMessageUtil lineMessageUtil;
        @Value("${here.link.comp-room}")
        private String hereLink;
        @Autowired
        private I18nMessageUtils i18nMessageUtils;
        @Autowired
        private ICompRoomEmailTargetService emailTargetService;
        @Autowired
        private MailInternalService mailInternalService;

        /**
         * 每天0点/12点邮件通知Guests In-House Complimentary报告中的免费房数据
         *
         * @param scheduler 调度任务
         * @return void
         * @author lichen
         * @date 2023/8/7
         */
        @Async
        public void autoNotify(CompRoomScheduler scheduler) {
            String alertEmailSubject = "[Warning] - Notify Comp Room";
            try {
                PropertyDTO propertyDTO = propertyI18nRedisService.get(scheduler.getPropertyId());
                if (!propertyDTO.getStatus()) return;

                //查询邮件配置
                CompRoomEmailConfig emailConfig = compRoomEmailConfigService.getByPropertyIdAndType(scheduler.getPropertyId(), scheduler.getCategory());
                if (Objects.isNull(emailConfig)) return;
                if (!emailConfig.getStatus()) {
                    log.info("NotifyCompRoomTask.end, email config status is false, propertyId:{},schedulerJobId:{},type:{}",
                            propertyDTO.getId(), scheduler.getId(), scheduler.getCategory());
                    return;
                }
                List<CompRoomEmailTarget> emailTargets = emailTargetService.listByConfigId(Lists.newArrayList(emailConfig.getId()));
                if (CollectionUtils.isEmpty(emailTargets)) return;

                //查询所有有效的免费房间
                List<RqCompRoomForm> compRoomList = compRoomFormService.listNotCheckOutCompRoomByNotifyRule(propertyDTO);
                if (CollectionUtils.isEmpty(compRoomList)) return;

                InternationalizationDateTimeDTO dateTime = propertyDTO.getInternationalization().getDateTime();
                String longDate = dateTime.getLongDate();
                String hourClock = dateTime.getHourClock();
                String timezone = propertyDTO.getTimezone();
                String language = propertyDTO.getLanguage();

                //用户集合
                List<Integer> userIds = compRoomList.stream().map(RqCompRoomForm::getCreatedBy).collect(Collectors.toList());
                Map<Integer, String> userId2Name = userInternalService.getNameMapByIds(propertyDTO.getTenantId(), userIds);
                //转换成vo
                List<CompRoomEmailVO> compRoomEmailVOS = beanMapper.mapList(compRoomList, CompRoomEmailVO.class, (entity, vo) -> {
                    vo.setCheckInDateStr(InternationalizationUtils.formatDateTime(vo.getCheckInDate(), longDate, StringUtils.EMPTY, timezone, language));
                    vo.setCheckOutDateStr(InternationalizationUtils.formatDateTime(vo.getCheckOutDate(), longDate, StringUtils.EMPTY, timezone, language));
                    vo.setCreatedTimeStr(InternationalizationUtils.formatDateTime(vo.getCreatedTime(), longDate, hourClock, timezone, language));

                    List<String> confirmationList = JsonUtils.convertStringToList(objectMapper, entity.getConfirmation(), String.class);
                    if (CollectionUtils.isNotEmpty(confirmationList)) {
                        vo.setConfirmations(StringUtils.join(confirmationList, ","));
                    }
                    vo.setCreatedByName(userId2Name.get(vo.getCreatedBy()));

                    //审批状态
                    String approveStatusDesc = i18nMessageUtils.message(ApproveStatusEnum.getI18nCode(vo.getApproveStatus()), language);
                    vo.setApproveStatusDesc(approveStatusDesc);
                });
                //发送通知
                sendNotify(propertyDTO, emailConfig, emailTargets, compRoomEmailVOS, scheduler.getCategory());
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                String alertEmailContent = MessageFormat.format("<p>propertyId:{0}</p>", scheduler.getPropertyId()) +
                        "<p>Exception occurred when notify comp room.</p>" +
                        e.getMessage();
                mailInternalService.sendAlertEmail(alertEmailSubject, alertEmailContent);
            }
        }

        /**
         * 发送通知
         *
         * @param openPropertyDTO     资产对象
         * @param emailConfig         邮件配置对象
         * @param emailTargets        邮件通知对象集合
         * @param compRoomEmailVOList 免费房数据
         * @return void
         * @author lichen
         * @date 2023/8/7
         */
        private void sendNotify(PropertyDTO openPropertyDTO, CompRoomEmailConfig emailConfig, List<CompRoomEmailTarget> emailTargets,
                                List<CompRoomEmailVO> compRoomEmailVOList, int notifyType) {
            String language = openPropertyDTO.getLanguage();
            String functionName = i18nMessageUtils.message(FunctionCons.COMP_ROOM, language);

            //跳转链接
            String linkUrl = MessageFormat.format(hereLink + "?fromPage=email&property={0}&tenant={1}", openPropertyDTO.getAbbr(), openPropertyDTO.getTenantSymbol());

            //默认主题的国际化code
            String defaultSubjectI18nCode = CompRoomNotifyConfigTypeEnum.getDefaultSubjectI18nCode(notifyType);
            String defaultSubject = i18nMessageUtils.message(defaultSubjectI18nCode, language, functionName, openPropertyDTO.getName());

            //自定义主体优先，其次默认主题
            String subject = StringUtils.isNotBlank(emailConfig.getSubject()) ? emailConfig.getSubject() : defaultSubject;

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

            /**
             * 生成邮件内容
             */
            Map<Boolean, List<CompRoomEmailVO>> isDateNow2ComplimentaryEmailVOS = compRoomEmailVOList.stream().collect(partitioningBy(item -> {
                Long checkOutDate = item.getCheckOutDate();
                Long dateNow = DateTimeUtils.dateNowTimestamp(openPropertyDTO.getTimezone());
                return checkOutDate.compareTo(dateNow) == BaseConstant.ZERO;
            }));
            //checkOutDate等于当天的数据
            List<CompRoomEmailVO> dateNowVoList = isDateNow2ComplimentaryEmailVOS.get(true);
            //checkOutDate不等于当天的数据
            List<CompRoomEmailVO> voList = isDateNow2ComplimentaryEmailVOS.get(false);
            Context context = new Context();
            context.setVariable("dateNowVoList", dateNowVoList);
            context.setVariable("voList", voList);
            context.setVariable("propertyName", openPropertyDTO.getName());
            context.setVariable("functionName", functionName);
            context.setVariable("hereLink", linkUrl);
            String mailBody = templateEngine.process("comproom/compRoom-checkedIn-statistics_" + language, context);
            notifyDTO.setEmailContent(EmailUtil.getFullEmailContent(defaultSubject, mailBody, language));

            LinkedHashMap<String, String> businessMap = new LinkedHashMap<>();
            businessMap.put(i18nMessageUtils.message(I18nConstant.I18N_TOTAL, language), compRoomEmailVOList.size() + "");

            PublicFlexMsgParm publicFlexMsgParm = PublicFlexMsgParm.builder()
                    .propertyName(openPropertyDTO.getName())
                    .propertyId(openPropertyDTO.getId())
                    .functionName(functionName)
                    .title("Comp room checked-in statistics")
                    .link(linkUrl)
                    .businessMap(businessMap)
                    .build();
            JSONObject lineMsg = lineMessageUtil.generatePublicFlexMsg(publicFlexMsgParm);
            notifyDTO.setLineContent(Lists.newArrayList(lineMsg));

            notifyInternalService.sendNotify(notifyDTO);
        }

    }