# DbDbPmsMarketCodeStatisticsServiceImpl.java

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

    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.cons.SystemPlatformEnum;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.InternationalizationUtils;
    import cloud.wconnect.commonlib.util.JsonUtils;
    import cloud.wconnect.workperformance.entity.database.DbPmsMarketCodeStatistics;
    import cloud.wconnect.workperformance.mapper.database.DbPmsMarketCodeStatisticsMapper;
    import cloud.wconnect.workperformance.pojo.bo.database.managerflash.DbPmsManagerFlashItemBO;
    import cloud.wconnect.workperformance.pojo.bo.database.marketcode.DbPmsMarketCodeStatisticsBO;
    import cloud.wconnect.workperformance.pojo.bo.database.marketcode.DbPmsMarketCodeStatisticsDataBO;
    import cloud.wconnect.workperformance.pojo.vo.database.marketcode.DbPmsMarketCodeStatisticsVO;
    import cloud.wconnect.workperformance.service.database.IDbPmsManagerFlashService;
    import cloud.wconnect.workperformance.service.database.IDbPmsMarketCodeStatisticsService;
    import cloud.wconnect.workperformance.service.database.marketcode.IDbPmsMarketCodeStatisticsParseService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import jakarta.annotation.Resource;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.stereotype.Service;

    import java.math.RoundingMode;
    import java.time.LocalDate;
    import java.util.Objects;

    /**
     * <p>
     * Database Market Code Statistics 服务实现类
     * </p>
     *
     * @author zc
     * @since 2025-12-12
     */
    @Service
    @DS("database")
    public class DbDbPmsMarketCodeStatisticsServiceImpl extends ServiceImpl<DbPmsMarketCodeStatisticsMapper, DbPmsMarketCodeStatistics> implements IDbPmsMarketCodeStatisticsService {

        @Lazy
        @Resource
        private IDbPmsManagerFlashService managerFlashService;
        @Resource
        private ObjectMapper objectMapper;

        /**
         * 处理报告数据
         *
         * @param propertyDTO 资产
         * @param bo          报告数据
         * @param operatorId  操作人 id
         * @author zc
         * @date 2025/12/12
         */
        @Override
        public void handle(PropertyDTO propertyDTO, DbPmsMarketCodeStatisticsBO bo, int operatorId) {
            LocalDate localDate = DateTimeUtils.strToLocalDate(bo.getDateStr(), BaseConstant.DATE_FORMAT_YYYY_MM_DD);
            long date = Long.parseLong(DateTimeUtils.localDateToStr(localDate, BaseConstant.DATE_FORMAT_YYYYMMDD));

            DbPmsMarketCodeStatistics marketCodeStatistics = getByDate(propertyDTO.getId(), date);
            if (Objects.isNull(marketCodeStatistics)) {
                marketCodeStatistics = new DbPmsMarketCodeStatistics();
                marketCodeStatistics.setPropertyId(propertyDTO.getId());
                marketCodeStatistics.setDate(date);
            }
            marketCodeStatistics.setData(JsonUtils.convertObjToString(objectMapper, bo.getData()));
            marketCodeStatistics.setUpdateBy(operatorId);
            marketCodeStatistics.setUpdateTime(DateTimeUtils.nowTimestamp());

            saveOrUpdate(marketCodeStatistics);
        }

        /**
         * 获取指定日期的数据
         *
         * @param propertyId 资产 id
         * @param date       日期（yyyyMMdd）
         * @return DbPmsMarketCodeStatistics
         * @author zc
         * @date 2026/1/12
         */
        private DbPmsMarketCodeStatistics getByDate(int propertyId, long date) {
            return getOne(new LambdaQueryWrapper<DbPmsMarketCodeStatistics>()
                    .eq(DbPmsMarketCodeStatistics::getPropertyId, propertyId)
                    .eq(DbPmsMarketCodeStatistics::getDate, date));
        }

        /**
         * 获取 Market code statistics 数据详情
         *
         * @param propertyId 资产 id
         * @param date       日期（yyyyMMdd）
         * @return DbPmsMarketCodeStatisticsVO
         * @author zc
         * @date 2026/1/12
         */
        @Override
        public DbPmsMarketCodeStatisticsVO getDetail(int propertyId, long date) {
            DbPmsMarketCodeStatistics marketCodeStatistics = getByDate(propertyId, date);
            if (Objects.isNull(marketCodeStatistics)) {
                return null;
            }
            return JsonUtils.convertStringToObject(objectMapper, marketCodeStatistics.getData(), DbPmsMarketCodeStatisticsVO.class);
        }

        /**
         * 导入 Manager flash 触发重新计算
         *
         * @param propertyDTO 资产
         * @param date        日期（yyyyMMdd）
         * @param scRoomsBO   SC房间数BO
         * @param operatorId  操作人 id
         * @author zc
         * @date 2026/1/12
         */
        @Override
        public void recalculateByManagerFlash(PropertyDTO propertyDTO, long date, DbPmsManagerFlashItemBO scRoomsBO, int operatorId) {
            /*
             * 因为 Opera 报告数据是完整的，不需要重新计算，所以不处理 Opera PMS 的资产；
             * Shiji、Other 报告中缺少父级、Total 的数据，解析报告时需要汇总计算父级、Total，但是无法计算 MTD、YTD 的 Occ.%，
             * 所以需要从对应日期的 Manager flash 报告中获取 MTD、YTD 的房间数来计算 Occ.%；
             * 每当 Manager flash 报告导入系统时，都需要触发重新计算 Market code statistics 数据
             */
            if (propertyDTO.getPmsType().equals(SystemPlatformEnum.OPERA.getDesc())) {
                return;
            }
            if (Objects.isNull(scRoomsBO)) {
                return;
            }
            // 若对应日期的 Market code statistics 数据不存在则不处理
            DbPmsMarketCodeStatistics marketCodeStatistics = getByDate(propertyDTO.getId(), date);
            if (Objects.isNull(marketCodeStatistics)) {
                return;
            }
            RoundingMode roundingMode = InternationalizationUtils.getRoundingMode(propertyDTO
                    .getInternationalization().getNumber().getCalculationRule());

            DbPmsMarketCodeStatisticsDataBO originDataBO = JsonUtils.convertStringToObject(objectMapper,
                    marketCodeStatistics.getData(), DbPmsMarketCodeStatisticsDataBO.class);

            // 计算每个父级的小计(MarketCode)
            IDbPmsMarketCodeStatisticsParseService.calculateParentSubtotalsOcc(originDataBO.getMarketCode(), scRoomsBO, roundingMode);

            // 计算总计(Total)
            IDbPmsMarketCodeStatisticsParseService.calculateTotalsOcc(originDataBO, scRoomsBO, roundingMode);

            // 更新数据
            marketCodeStatistics.setData(JsonUtils.convertObjToString(objectMapper, originDataBO));
            marketCodeStatistics.setUpdateBy(operatorId);
            marketCodeStatistics.setUpdateTime(DateTimeUtils.nowTimestamp());
            updateById(marketCodeStatistics);
        }
    }