# OvertimeWidgetServiceImpl.java

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

    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.workperformance.entity.mor.Overtime;
    import cloud.wconnect.workperformance.pojo.dto.mor.overtime.widget.OvertimeAmountDTO;
    import cloud.wconnect.workperformance.pojo.dto.mor.overtime.widget.OvertimeAmountsDTO;
    import cloud.wconnect.workperformance.pojo.query.mor.overtime.OvertimeAmountQuery;
    import cloud.wconnect.workperformance.service.mor.IOvertimeService;
    import cloud.wconnect.workperformance.service.mor.IOvertimeWidgetService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.google.common.collect.Lists;
    import org.apache.commons.collections.CollectionUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;

    import java.math.BigDecimal;
    import java.time.ZonedDateTime;
    import java.util.Collections;
    import java.util.List;
    import java.util.Map;
    import java.util.stream.Collectors;

    /**
     * Service: widget
     *
     * @author zc
     * @date 2023/12/09
     */
    @Service
    @DS("work_performance")
    public class OvertimeWidgetServiceImpl implements IOvertimeWidgetService {

        @Autowired
        private IOvertimeService overtimeService;

        /**
         * 获取加班费用
         *
         * @param propertyList 资产
         * @param query        查询条件
         * @return OvertimeAmountsDTO 集合
         * @author zc
         * @date 2023/12/9
         */
        @Override
        public List<OvertimeAmountsDTO> listAmounts(List<PropertyDTO> propertyList, OvertimeAmountQuery 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<Overtime>> month2OvertimeList = overtimeService.list(new QueryWrapper<Overtime>().lambda()
                                .eq(Overtime::getPropertyId, property.getId())
                                .between(Overtime::getStartOfMonth, fromDate, toDate)).stream()
                        .collect(Collectors.groupingBy(Overtime::getStartOfMonth));

                List<OvertimeAmountDTO> values = Lists.newArrayList();
                for (ZonedDateTime date = fromZonedDate; !date.isAfter(toZonedDate); date = date.plusMonths(1)) {
                    List<Overtime> houseList = month2OvertimeList.getOrDefault(date.toEpochSecond(), Collections.emptyList());
                    BigDecimal amount = houseList.stream().map(Overtime::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                    values.add(OvertimeAmountDTO.builder()
                            .date(DateTimeUtils.parseZonedDateTimeToStr(date, BaseConstant.DATE_FORMAT_YYYY_MM))
                            .value(amount)
                            .build());
                }

                return OvertimeAmountsDTO.builder()
                        .propertyId(property.getId())
                        .propertyName(property.getAbbr())
                        .values(values)
                        .build();
            }).toList();
        }
    }