# DbDbPmsHfHistoryServiceImpl.java

    package cloud.wconnect.workperformance.service.database.impl;

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.pojo.dto.ListPagedDTO;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.JsonUtils;
    import cloud.wconnect.workperformance.cons.database.DbCons;
    import cloud.wconnect.workperformance.entity.database.DbPmsHfHistory;
    import cloud.wconnect.workperformance.mapper.database.DbPmsHfHistoryMapper;
    import cloud.wconnect.workperformance.pojo.bo.database.historyforecast.DbPmsHfBO;
    import cloud.wconnect.workperformance.pojo.dto.database.historyforecast.DbPmsHfHistoryDTO;
    import cloud.wconnect.workperformance.pojo.query.database.DbPmsHfQuery;
    import cloud.wconnect.workperformance.pojo.vo.database.historyforecast.DbPmsHfVO;
    import cloud.wconnect.workperformance.service.database.IDbPmsHfHistoryService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import jakarta.annotation.Resource;
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import java.time.LocalDate;
    import java.util.Comparator;
    import java.util.List;

    /**
     * <p>
     * Database History and Forecast - History 服务实现类
     * </p>
     *
     * @author zc
     * @since 2026-01-04
     */
    @Service
    @DS("database")
    public class DbDbPmsHfHistoryServiceImpl extends ServiceImpl<DbPmsHfHistoryMapper, DbPmsHfHistory> implements IDbPmsHfHistoryService {

        @Resource
        private BeanMapper beanMapper;
        @Resource
        private ObjectMapper objectMapper;

        /**
         * 处理报告数据
         *
         * @param propertyDTO  资产
         * @param boList       报告数据
         * @param businessDate 营业日期(yyyyMMdd)
         * @param operatorId   操作人 id
         * @author zc
         * @date 2026/1/5
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void handle(PropertyDTO propertyDTO, List<DbPmsHfBO> boList, long businessDate, int operatorId) {
            if (CollectionUtils.isEmpty(boList)) {
                return;
            }

            List<DbPmsHfBO> historyBOList;

            String operaDataType = boList.get(0).getOperaDataType();
            // operaDataType 不等于空时，说明数据是从 Opera xml 文件中解析的
            if (StringUtils.isNotBlank(operaDataType)) {
                historyBOList = boList.stream().filter(bo -> {
                    LocalDate localDate = DateTimeUtils.strToLocalDate(bo.getDStr(), BaseConstant.DATE_FORMAT_YYYY_MM_DD);
                    long date = Long.parseLong(DateTimeUtils.localDateToStr(localDate, BaseConstant.DATE_FORMAT_YYYYMMDD));
                    return DbCons.HF_REPORT_DATA_HISTORY.equals(bo.getOperaDataType())
                            && (date < businessDate);
                }).toList();
            } else {
                historyBOList = boList.stream().filter(bo -> {
                    LocalDate localDate = DateTimeUtils.strToLocalDate(bo.getDStr(), BaseConstant.DATE_FORMAT_YYYY_MM_DD);
                    long date = Long.parseLong(DateTimeUtils.localDateToStr(localDate, BaseConstant.DATE_FORMAT_YYYYMMDD));
                    return date < businessDate;
                }).toList();
            }

            if (CollectionUtils.isEmpty(historyBOList)) {
                return;
            }

            int propertyId = propertyDTO.getId();
            long nowTimestamp = DateTimeUtils.nowTimestamp();
            List<DbPmsHfHistory> historyList = beanMapper.mapList(historyBOList, DbPmsHfHistory.class, (bo, entity) -> {
                entity.setPropertyId(propertyId);

                LocalDate localDate = DateTimeUtils.strToLocalDate(bo.getDStr(), BaseConstant.DATE_FORMAT_YYYY_MM_DD);
                long date = Long.parseLong(DateTimeUtils.localDateToStr(localDate, BaseConstant.DATE_FORMAT_YYYYMMDD));
                entity.setDate(date);
                DbPmsHfHistoryDTO historyDTO = beanMapper.map(bo, DbPmsHfHistoryDTO.class);
                entity.setData(JsonUtils.convertObjToString(objectMapper, historyDTO));
                entity.setUpdateBy(operatorId);
                entity.setUpdateTime(nowTimestamp);
            });

            // 按唯一索引字段排序，避免死锁
            historyList.sort(Comparator.comparing(DbPmsHfHistory::getPropertyId)
                    .thenComparing(DbPmsHfHistory::getDate));

            baseMapper.insertOrUpdateBatchByUnique(historyList);
        }

        /**
         * 获取指定日期范围的 History and forecast 数据
         *
         * @param propertyId 资产 id
         * @param query      查询条件
         * @return DbPmsHfVO 集合
         * @author zc
         * @date 2026/1/12
         */
        @Override
        public ListPagedDTO<DbPmsHfVO> list(int propertyId, DbPmsHfQuery query) {
            LambdaQueryWrapper<DbPmsHfHistory> queryWrapper = new LambdaQueryWrapper<DbPmsHfHistory>()
                    .eq(DbPmsHfHistory::getPropertyId, propertyId)
                    .between(DbPmsHfHistory::getDate, query.getStartDate(), query.getEndDate())
                    .orderByAsc(DbPmsHfHistory::getDate);
            Page<DbPmsHfHistory> page = page(new Page<>(query.getPage(), query.getSize()), queryWrapper);
            if (CollectionUtils.isEmpty(page.getRecords())) {
                return new ListPagedDTO<>();
            }

            List<DbPmsHfVO> voList = page.getRecords().stream().map(entity -> {
                DbPmsHfHistoryDTO dto = JsonUtils.convertStringToObject(objectMapper, entity.getData(), DbPmsHfHistoryDTO.class);
                DbPmsHfVO vo = beanMapper.map(dto, DbPmsHfVO.class);
                vo.setDate(entity.getDate());
                return vo;
            }).toList();
            return new ListPagedDTO<>(page.getTotal(), voList);
        }
    }