# AutoCreateHkInventory.java

    package cloud.wconnect.workperformance.businesstask.hkinventory;

    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.workperformance.service.hkinventory.IHkInventoryService;
    import com.google.common.collect.Lists;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.collections4.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.text.MessageFormat;
    import java.time.LocalDateTime;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    import java.util.stream.Collectors;

    /**
     * 每个月月末自动创建下个月的报告，创建时关联采购单
     *
     * @author lichen
     * @date 2025/4/25
     */
    @Slf4j
    @Component
    public class AutoCreateHkInventory {

        @Autowired
        private RedisTemplate<String, Object> redisTemplate;
        @Autowired
        private PropertyInternalService propertyInternalService;
        @Autowired
        private IHkInventoryService hkInventoryService;
        @Autowired
        private MailInternalService mailInternalService;
        /**
         * 默认时区
         */
        @Value("${default.timezone}")
        private String defaultTimezone;
        private static final String prefixKey = "wconnect:task:create-hk-inventory:";

        /**
         * 每月25号创建下月的Housekeeping Inventory
         *
         * @return void
         * @author lichen
         * @date 2025/4/25
         */
        @Scheduled(cron = "${schedule.cron.hk-inventory.create-hk-inventory}", zone = "${default.timezone}")
        public void create() {
            String currentDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern(BaseConstant.DATE_FORMAT_YYYYMM));
            if (!preventConcurrency(prefixKey + currentDate)) {
                return;
            }
            // 过滤出有效的资产
            List<PropertyDTO> openPropertyList = propertyInternalService.getOpenFunctionProperty(OpenFunctionPropertyQuery.builder()
                            .openFunctionIds(Lists.newArrayList(FunctionIdConstant.HOUSEKEEPING_INVENTORY)).build()).stream()
                    .filter(PropertyDTO::getStatus).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(openPropertyList)) {
                log.info("AutoCreateHkInventory.create end... openPropertyList is empty");
                return;
            }

            // 获取下月的月份（yyyyMM）
            ZonedDateTime zonedDateTime = DateTimeUtils.dateTimeNow(defaultTimezone).plusMonths(1);
            String yearMonth = zonedDateTime.format(DateTimeFormatter.ofPattern(BaseConstant.DATE_FORMAT_YYYYMM));
            int year = zonedDateTime.getYear();
            int month = zonedDateTime.getMonthValue();

            try {
                // 创建Housekeeping Inventory数据
                hkInventoryService.createHkInventory(openPropertyList, year, month);
            } catch (Exception e) {
                log.error("AutoCreateHkInventory.create error:" + e.getMessage(), e);
                String mailContent = MessageFormat.format("Business:{0}<br/>Content:{1}", "AutoCreateHkInventory",
                        "There is something wrong when auto create Housekeeping Inventory.Exception: " + e.getMessage());
                mailInternalService.sendAlertEmail("[Warning] - Create Housekeeping Inventory - " + yearMonth, mailContent);
            }
            log.info("AutoCreateHkInventory.create end...");
        }

        /**
         * 校验是否并发执行
         *
         * @param key 缓存前缀
         * @return java.lang.Boolean
         * @author lichen
         * @date 2025/4/25
         */
        private Boolean preventConcurrency(String key) {
            return redisTemplate.opsForValue().setIfAbsent(key, 0, 1, TimeUnit.DAYS);
        }

    }