# HkInventoryNoPublishNotify.java

    package cloud.wconnect.workperformance.businesstask.hkinventory;

    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.line.PublicFlexMsgParm;
    import cloud.wconnect.commonlib.redis.PropertyI18nRedisService;
    import cloud.wconnect.commonlib.service.MailInternalService;
    import cloud.wconnect.commonlib.service.NotifyInternalService;
    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.workperformance.cons.FunctionPointEnum;
    import cloud.wconnect.workperformance.cons.hkinventory.HkInventoryNotifyConfigTypeEnum;
    import cloud.wconnect.workperformance.cons.hkinventory.StatusEnum;
    import cloud.wconnect.workperformance.entity.hkinventory.HkInventory;
    import cloud.wconnect.workperformance.entity.hkinventory.HkInventoryEmailConfig;
    import cloud.wconnect.workperformance.entity.hkinventory.HkInventoryEmailTarget;
    import cloud.wconnect.workperformance.entity.hkinventory.HkInventoryScheduler;
    import cloud.wconnect.workperformance.service.hkinventory.IHkInventoryEmailConfigService;
    import cloud.wconnect.workperformance.service.hkinventory.IHkInventoryEmailTargetService;
    import cloud.wconnect.workperformance.service.hkinventory.IHkInventoryService;
    import com.alibaba.fastjson.JSONObject;
    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.time.ZonedDateTime;
    import java.util.List;
    import java.util.Objects;

    /**
     * Housekeeping Inventory未发布时发送通知
     *
     * @author lichen
     * @date 2025/4/25
     */
    @Slf4j
    @Component
    public class HkInventoryNoPublishNotify {

        @Autowired
        private PropertyI18nRedisService propertyI18nRedisService;
        @Autowired
        private IHkInventoryEmailConfigService emailConfigService;
        @Autowired
        private IHkInventoryEmailTargetService emailTargetService;
        @Autowired
        private IHkInventoryService hkInventoryService;
        @Autowired
        private MailInternalService mailInternalService;
        @Autowired
        private NotifyInternalService notifyInternalService;
        @Autowired
        private LineMessageUtil lineMessageUtil;
        @Autowired
        private I18nMessageUtils i18nMessageUtils;
        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private TemplateEngine templateEngine;
        @Value("${here.link.housekeeping-inventory}")
        private String hereLink;

        /**
         * Housekeeping 未发布时发送通知
         *
         * @param scheduler 定时任务
         * @return void
         * @author lichen
         * @date 2025/4/25
         */
        @Async
        public void process(HkInventoryScheduler scheduler) {
            String alertEmailSubject = "[Warning] - Notify no publish Housekeeping Inventory";
            try {
                PropertyDTO propertyDTO = propertyI18nRedisService.get(scheduler.getPropertyId());
                if (!propertyDTO.getStatus()) return;

                //查询邮件配置信息
                HkInventoryEmailConfig emailConfig = emailConfigService.getByPropertyIdAndType(scheduler.getPropertyId(), scheduler.getCategory());
                if (Objects.isNull(emailConfig)) return;
                if (!emailConfig.getStatus()) {
                    log.info("HkInventoryNoPublishNotify.end, email config status is false, propertyId:{},scheduler:{},type:{}",
                            propertyDTO.getId(), scheduler.getId(), scheduler.getCategory());
                    return;
                }

                List<HkInventoryEmailTarget> emailTargets = emailTargetService.listByConfigId(emailConfig.getId());
                if (CollectionUtils.isEmpty(emailTargets)) {
                    log.info("HkInventoryNoPublishNotify.end, email target is empty, propertyId:{},scheduler:{},type:{}",
                            propertyDTO.getId(), scheduler.getId(), scheduler.getCategory());
                    return;
                }

                //上个月的日期
                ZonedDateTime preZonedDateTime = DateTimeUtils.dateNow(propertyDTO.getTimezone()).minusMonths(1);
                String preYearMonth = DateTimeUtils.parseZonedDateTimeToStr(preZonedDateTime, BaseConstant.DATE_FORMAT_YYYY_MM);

                List<HkInventory> hkInventoryList = hkInventoryService.listByCondition(propertyDTO.getId(), preZonedDateTime.getYear(), preZonedDateTime.getMonthValue(),
                        StatusEnum.PENDING.getStatus());
                if (CollectionUtils.isEmpty(hkInventoryList)) {
                    log.info("HkInventoryNoPublishNotify.end, The Housekeeping Inventory of last month has been released, propertyId:{},scheduler:{},type:{}",
                            propertyDTO.getId(), scheduler.getId(), scheduler.getCategory());
                    return;
                }

                //上个月的数据只有1条
                HkInventory hkInventory = hkInventoryList.get(0);

                //下个月的housekeeping Inventory
                HkInventory nextInventory = hkInventoryService.getNextInventory(hkInventory);

                //发送通知
                sendNotify(propertyDTO, hkInventory, emailConfig, emailTargets, preYearMonth, scheduler.getCategory(), nextInventory);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                String alertEmailContent = MessageFormat.format("<p>propertyId:{0}</p>", scheduler.getPropertyId()) +
                        "<p>Send notifications when Housekeeping Inventory is not released,Exception:</p>" +
                        e.getMessage();
                mailInternalService.sendAlertEmail(alertEmailSubject, alertEmailContent);
            }
        }

        /**
         * 发送通知
         *
         * @param propertyDTO   资产DTO
         * @param hkInventory   未发布的Housekeeping Inventory
         * @param emailConfig   邮件配置
         * @param emailTargets  邮件通知对象
         * @param yearMonth     年月（格式yyyyMM）
         * @param notifyType    通知类型
         * @param nextInventory 下个月的Housekeeping Inventory
         * @return void
         * @author lichen
         * @date 2025/4/25
         */
        private void sendNotify(PropertyDTO propertyDTO, HkInventory hkInventory, HkInventoryEmailConfig emailConfig,
                                List<HkInventoryEmailTarget> emailTargets, String yearMonth, int notifyType, HkInventory nextInventory) {
            String language = propertyDTO.getLanguage();
            //通知功能点
            FunctionPointEnum functionPointEnum = HkInventoryNotifyConfigTypeEnum.getFunctionPointEnum(notifyType);
            //功能名称
            String functionName = i18nMessageUtils.message(FunctionCons.HOUSEKEEPING_INVENTORY, language);

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

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

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

            String nextStatus = Objects.nonNull(nextInventory) ? nextInventory.getStatus().toString() : "";
            //生成邮件通知内容
            String urlParams = MessageFormat.format("?id={0}&type={1}&property={2}&tenant={3}&nextStatus={4}",
                    hkInventory.getId(),
                    notifyType == HkInventoryNotifyConfigTypeEnum.NOTIFY_FORM_FILLER.getType() ? "edit" : "view",
                    propertyDTO.getAbbr(), propertyDTO.getTenantSymbol(), nextStatus);
            String link = hereLink + urlParams;
            Context context = new Context();
            context.setVariable("propertyName", propertyDTO.getName());
            context.setVariable("functionName", functionName);
            context.setVariable("yearMonth", yearMonth);
            context.setVariable("hereLink", link);
            context.setVariable("notifyType", notifyType);
            String mailBody = templateEngine.process("hkinventory/not-published_" + language, context);
            notifyDTO.setEmailContent(EmailUtil.getFullEmailContent(defaultSubject, mailBody, language));

            //生成line通知内容
            PublicFlexMsgParm publicFlexMsgParm = PublicFlexMsgParm.builder()
                    .propertyName(propertyDTO.getName())
                    .propertyId(propertyDTO.getId())
                    .functionName(functionName)
                    .title(MessageFormat.format("The data for {0} has not been released", yearMonth))
                    .link(link)
                    .businessMap(null)
                    .build();
            JSONObject lineContent = lineMessageUtil.generatePublicFlexMsg(publicFlexMsgParm);
            notifyDTO.setLineContent(Lists.newArrayList(lineContent));

            notifyInternalService.sendNotify(notifyDTO);
        }

    }