# HotelKpiExplainMonthlyServiceImpl.java

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

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.util.InternationalizationUtils;
    import cloud.wconnect.commonlib.util.YearMonthUtils;
    import cloud.wconnect.workperformance.entity.hotelkpi.HotelKpiExplainMonthly;
    import cloud.wconnect.workperformance.mapper.hotelkpi.HotelKpiExplainMonthlyMapper;
    import cloud.wconnect.workperformance.pojo.dto.hotelkpi.explain.HotelKpiExplainDTO;
    import cloud.wconnect.workperformance.service.hotelkpi.IHotelKpiExplainMonthlyService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import jakarta.annotation.Resource;
    import org.apache.commons.collections.CollectionUtils;
    import org.springframework.stereotype.Service;

    import java.math.BigDecimal;
    import java.math.RoundingMode;
    import java.time.YearMonth;
    import java.util.Collections;
    import java.util.List;
    import java.util.Objects;

    /**
     * <p>
     * Hotel KPI Explain 服务实现类
     * </p>
     *
     * @author zc
     * @since 2024-06-26
     */
    @Service
    @DS("work_performance")
    public class HotelKpiExplainMonthlyServiceImpl extends ServiceImpl<HotelKpiExplainMonthlyMapper, HotelKpiExplainMonthly> implements IHotelKpiExplainMonthlyService {

        @Resource
        private BeanMapper beanMapper;

        /**
         * 根据指定年份、指标获取 Explain DTO 数据
         *
         * @param propertyId  资产 id
         * @param year        目标年(yyyy)
         * @param metricsType 指标类型
         * @return HotelKpiExplainDTO 集合
         * @author zc
         * @date 2024/6/28
         */
        @Override
        public List<HotelKpiExplainDTO> listByYearAndMetricsType(int propertyId, long year, int metricsType) {
            long startMonth = YearMonthUtils.parseYearMonthToLong(YearMonth.of((int) year, 1));
            long endMonth = YearMonthUtils.parseYearMonthToLong(YearMonth.of((int) year, 12));

            List<HotelKpiExplainMonthly> explainMonthlyList = list(new LambdaQueryWrapper<HotelKpiExplainMonthly>()
                    .between(HotelKpiExplainMonthly::getMonth, startMonth, endMonth)
                    .eq(HotelKpiExplainMonthly::getPropertyId, propertyId));
            if (CollectionUtils.isEmpty(explainMonthlyList)) {
                return Collections.emptyList();
            }
            return beanMapper.mapList(explainMonthlyList, HotelKpiExplainDTO.class,
                    (entity, dto) -> dto.setDate(entity.getMonth()));
        }

        /**
         * 保存 Explain 数据
         *
         * @param propertyDTO 资产
         * @param saveDTO     保存数据
         * @author zc
         * @date 2025/8/26
         */
        @Override
        public void save(PropertyDTO propertyDTO, HotelKpiExplainDTO saveDTO) {
            HotelKpiExplainMonthly explain = new HotelKpiExplainMonthly();
            explain.setPropertyId(propertyDTO.getId());
            explain.setMonth(saveDTO.getDate());

            RoundingMode roundingMode = InternationalizationUtils.getRoundingMode(propertyDTO
                    .getInternationalization().getNumber().getCalculationRule());
            BigDecimal value = saveDTO.getValue();
            if (Objects.nonNull(value)) {
                value = value.setScale(BaseConstant.DATA_PRECISION, roundingMode);
            }
            explain.setValue(value);

            baseMapper.insertOrUpdateByUnique(explain);
        }
    }