# AutoClosedTask.java

    package cloud.wconnect.it.businesstask.servicerequestcenter;

    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.cons.FunctionIdConstant;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.pojo.query.OpenFunctionPropertyQuery;
    import cloud.wconnect.commonlib.service.MailInternalService;
    import cloud.wconnect.commonlib.service.PropertyInternalService;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.it.entity.servicerequestcenter.ServiceRequestCenter;
    import cloud.wconnect.it.service.servicerequestcenter.IServiceRequestCenterService;
    import cloud.wconnect.it.service.servicerequestcenter.IServiceRequestOperaRequestService;
    import com.google.common.collect.Lists;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.collections.CollectionUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;

    import java.util.List;
    import java.util.concurrent.TimeUnit;
    import java.util.stream.Collectors;

    /**
     * @author: yyt
     * 2025-12-19
     */
    @Slf4j
    @Component
    public class AutoClosedTask {

        @Autowired
        private PropertyInternalService propertyInternalService;
        @Autowired
        private RedisTemplate<String, Object> redisTemplate;
        @Autowired
        private MailInternalService mailInternalService;
        @Autowired
        private IServiceRequestCenterService serviceRequestCenterService;
        @Autowired
        private IServiceRequestOperaRequestService serviceRequestOperaRequestService;

        @Value("${default.timezone}")
        private String defaultTimezone;

        private static final String PREFIX_KEY = "wconnect:task:service-request-center-auto-closed:";

        /**
         * 自动关闭超7天未 close 的 request
         *
         * @author yyt
         * @date 2025/12/19
         **/
        @Scheduled(cron = "${schedule.cron.notify.service-request-center-auto-closed}", zone = "${default.timezone}")
        public void autoClosed() {
            String currentDateStr = DateTimeUtils.dateNowStr(defaultTimezone, BaseConstant.DATE_FORMAT_YYMMDDHH);
            if (!preventConcurrency(PREFIX_KEY + currentDateStr)) {
                return;
            }

            log.info("AutoClosedTask... start");
            String alertTitle = "[Warning] - Exceptions About Auto Closed Request";
            StringBuilder warningEmail = new StringBuilder("<p>There is something wrong when auto closed request.</p>");

            try {
                // 查询开通此功能 的资产
                List<PropertyDTO> openModuleProperty = propertyInternalService.getOpenFunctionProperty(OpenFunctionPropertyQuery.builder()
                        .openFunctionIds(Lists.newArrayList(FunctionIdConstant.DASHBOARD)).build());
                if (CollectionUtils.isEmpty(openModuleProperty)) {
                    log.info("AutoClosedTask... there is no open module property");
                    log.info("AutoClosedTask... end");
                    return;
                }

                // 循环处理每个租户的数据
                openModuleProperty.stream().collect(Collectors.groupingBy(PropertyDTO::getTenantId))
                        .forEach((tenantId, propertyDTOList)->{

                            // 查询超过7天未 close 的 request
                            List<ServiceRequestCenter> unclosedRequests = serviceRequestCenterService.listUnclosedRequests(tenantId);
                            if (CollectionUtils.isEmpty(unclosedRequests)) {
                                log.info("AutoClosedTask... there is no unclosed request, tenantId: {}", tenantId);
                                return;
                            }

                            // 通知用户
                            serviceRequestOperaRequestService.autoClosedRequest(tenantId, propertyDTOList, unclosedRequests);
                        });
            } catch (Exception e) {
                warningEmail.append("<p>Exception: ").append(e.getMessage()).append("</p>");
                mailInternalService.sendAlertEmail(alertTitle, warningEmail.toString());
                log.error("AutoClosedTask... error", e);
            }

            log.info("AutoClosedTask... end");
        }

        /**
         * 防止并发
         *
         * @param key 唯一标识
         * @return 锁成功
         * @author yyt
         * @date 2025/12/19
         */
        private Boolean preventConcurrency(String key) {
            return redisTemplate.opsForValue().setIfAbsent(key, 0, 1, TimeUnit.DAYS);
        }

    }