# HkEfficiencyWidgetServiceImpl.java

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

    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.InternationalizationUtils;
    import cloud.wconnect.workperformance.entity.hkefficiency.HkEfficiency;
    import cloud.wconnect.workperformance.pojo.dto.hkefficiency.widget.HkEfficiencyAverageHourDTO;
    import cloud.wconnect.workperformance.pojo.dto.hkefficiency.widget.HkEfficiencyAverageHoursDTO;
    import cloud.wconnect.workperformance.pojo.query.hkefficiency.HkEfficiencyAverageHoursQuery;
    import cloud.wconnect.workperformance.service.hkefficiency.IHkEfficiencyService;
    import cloud.wconnect.workperformance.service.hkefficiency.IHkEfficiencyWidgetService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.google.common.collect.Lists;
    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.ZonedDateTime;
    import java.util.Collections;
    import java.util.List;
    import java.util.Map;
    import java.util.Objects;
    import java.util.stream.Collectors;

    /**
     * Service: widget
     *
     * @author zc
     * @date 2023/12/09
     */
    @Service
    @DS("work_performance")
    public class HkEfficiencyWidgetServiceImpl implements IHkEfficiencyWidgetService {
        @Resource
        private IHkEfficiencyService hkEfficiencyService;

        /**
         * 获取单间房平均耗时数据
         *
         * @param propertyList 资产
         * @param query        查询条件
         * @return HousekeepingEfficiencyAverageHoursDTO 集合
         * @author zc
         * @date 2023/12/9
         */
        @Override
        public List<HkEfficiencyAverageHoursDTO> listAverageHours(List<PropertyDTO> propertyList,
                                                                  HkEfficiencyAverageHoursQuery query) {
            if (CollectionUtils.isEmpty(propertyList)) {
                return Collections.emptyList();
            }
            return propertyList.stream().map(property -> {
                long fromDate = DateTimeUtils.dateStrToEpochSecond(query.getStartDate().toString(),
                        BaseConstant.DATE_FORMAT_YYYYMMDD, property.getTimezone());
                ZonedDateTime fromZonedDate = DateTimeUtils.toZonedDateTime(fromDate, property.getTimezone());

                long toDate = DateTimeUtils.dateStrToEpochSecond(query.getEndDate().toString(),
                        BaseConstant.DATE_FORMAT_YYYYMMDD, property.getTimezone());
                ZonedDateTime toZonedDate = DateTimeUtils.toZonedDateTime(toDate, property.getTimezone());

                Map<Long, List<HkEfficiency>> month2HouseList =
                        hkEfficiencyService.list(new QueryWrapper<HkEfficiency>().lambda()
                                        .eq(HkEfficiency::getPropertyId, property.getId())
                                        .between(HkEfficiency::getTheDate, fromDate, toDate)).stream()
                                .collect(Collectors.groupingBy(HkEfficiency::getStartOfMonth));

                // 获取国际化数字配置
                RoundingMode roundingMode = InternationalizationUtils.getRoundingMode(property
                        .getInternationalization().getNumber().getCalculationRule());

                List<HkEfficiencyAverageHourDTO> values = Lists.newArrayList();
                for (ZonedDateTime date = fromZonedDate; !date.isAfter(toZonedDate); date = date.plusMonths(1)) {
                    List<HkEfficiency> houseList = month2HouseList.getOrDefault(date.toEpochSecond(), Collections.emptyList());
                    // 月总工作时数
                    BigDecimal hoursWorkedTotal = houseList.stream().map(HkEfficiency::getHoursWorked)
                            .filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                    // 月总售房数量
                    int roomsRentedTotal = houseList.stream().map(HkEfficiency::getRoomsRented)
                            .filter(Objects::nonNull).reduce(Integer::sum).orElse(BaseConstant.ZERO);
                    // 单间房耗时均值
                    BigDecimal averageHours = (roomsRentedTotal == 0) ? BigDecimal.ZERO :
                            hoursWorkedTotal.divide(BigDecimal.valueOf(roomsRentedTotal), BaseConstant.DATA_PRECISION, roundingMode);

                    values.add(HkEfficiencyAverageHourDTO.builder()
                            .date(DateTimeUtils.parseZonedDateTimeToStr(date, BaseConstant.DATE_FORMAT_YYYY_MM))
                            .value(averageHours)
                            .build());
                }
                return HkEfficiencyAverageHoursDTO.builder()
                        .propertyId(property.getId())
                        .propertyName(property.getAbbr())
                        .values(values)
                        .build();
            }).toList();
        }
    }