# SvaInternalServiceImpl.java

    package cloud.wconnect.workperformance.service.sva.internal.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.DateTimeUtils;
    import cloud.wconnect.workperformance.entity.sva.saleforecast.SaleForecast;
    import cloud.wconnect.workperformance.entity.sva.setting.FirstDay;
    import cloud.wconnect.workperformance.pojo.dto.sva.internal.SaleForecastInternalDTO;
    import cloud.wconnect.workperformance.pojo.dto.sva.internal.departmenthour.DepHourStatisticsInternalDTO;
    import cloud.wconnect.workperformance.pojo.query.sva.schedulevsactual.SvaHoursStatisticsQuery;
    import cloud.wconnect.workperformance.service.sva.internal.ISvaInternalService;
    import cloud.wconnect.workperformance.service.sva.saleforecast.ISaleForecastService;
    import cloud.wconnect.workperformance.service.sva.scheduleactual.ISvaDepCategoryHoursStatisticsService;
    import cloud.wconnect.workperformance.service.sva.setting.IFirstDayService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import jakarta.annotation.Resource;
    import org.apache.commons.collections.CollectionUtils;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Service;

    import java.time.LocalDate;
    import java.time.temporal.ChronoField;
    import java.util.Collections;
    import java.util.List;
    import java.util.Objects;

    /**
     * Internal Service
     *
     * @author zc
     * @date 2024/10/15
     */
    @Service
    @DS("work_performance")
    public class SvaInternalServiceImpl implements ISvaInternalService {
        @Resource
        private ISaleForecastService saleForecastService;
        @Resource
        private ISvaDepCategoryHoursStatisticsService depCategoryHoursStatisticsService;
        @Resource
        private IFirstDayService firstDayService;
        @Resource
        private BeanMapper beanMapper;

        @Value("${default.first-day.sva-setting}")
        private Integer defaultFirstDayOfWeek;

        /**
         * 获取指定日期所在周的第一天
         *
         * @param propertyId 资产 id
         * @param localDate  日期
         * @return LocalDate
         * @author zc
         * @date 2024/10/17
         */
        @Override
        public LocalDate getFirstDayOfWeek(int propertyId, LocalDate localDate) {
            FirstDay firstDay = firstDayService.get(propertyId);
            long firstDayOfWeek = Objects.isNull(firstDay) ? defaultFirstDayOfWeek : firstDay.getFirstDay();
            return (localDate.getDayOfWeek().getValue() >= firstDayOfWeek) ? localDate.with(ChronoField.DAY_OF_WEEK, firstDayOfWeek) :
                    localDate.minusWeeks(1).with(ChronoField.DAY_OF_WEEK, firstDayOfWeek);
        }

        /**
         * 获取指定日期范围内的 Sale Forecast
         *
         * @param propertyDTO 资产
         * @param startDate   开始日期(yyyyMMdd)
         * @param endDate     结束日期(yyyyMMdd)
         * @return SaleForecastInternalDTO 集合
         * @author zc
         * @date 2024/10/15
         */
        @Override
        public List<SaleForecastInternalDTO> listSaleForecast(PropertyDTO propertyDTO, long startDate, long endDate) {
            List<SaleForecast> saleForecastList = saleForecastService.list(new LambdaQueryWrapper<SaleForecast>()
                    .eq(SaleForecast::getPropertyId, propertyDTO.getId())
                    .between(SaleForecast::getTheDate,
                            DateTimeUtils.dateStrToEpochSecond(String.valueOf(startDate),
                                    BaseConstant.DATE_FORMAT_YYYYMMDD, propertyDTO.getTimezone()),
                            DateTimeUtils.dateStrToEpochSecond(String.valueOf(endDate),
                                    BaseConstant.DATE_FORMAT_YYYYMMDD, propertyDTO.getTimezone())));
            if (CollectionUtils.isEmpty(saleForecastList)) {
                return Collections.emptyList();
            }
            return beanMapper.mapList(saleForecastList, SaleForecastInternalDTO.class, (item, dto) -> {
                long theDate = Long.parseLong(DateTimeUtils.timestampToStr(item.getTheDate(),
                        BaseConstant.DATE_FORMAT_YYYYMMDD, propertyDTO.getTimezone()));
                dto.setTheDate(theDate);
            });
        }

        /**
         * 获取指定日期范围内的指定部门分类工时统计信息
         *
         * @param propertyDTO    资产
         * @param startDate      开始日期(yyyyMMdd)
         * @param endDate        结束日期(yyyyMMdd)
         * @param departmentCode 部门编号
         * @return DepartmentCategoryStatisticsInternalDTO
         * @author zc
         * @date 2025/1/13
         */
        @Override
        public DepHourStatisticsInternalDTO getDepartmentCategoryStatistics(PropertyDTO propertyDTO, long startDate, long endDate, String departmentCode) {
            long fromDate = DateTimeUtils.dateStrToEpochSecond(String.valueOf(startDate), BaseConstant.DATE_FORMAT_YYYYMMDD, propertyDTO.getTimezone());
            long toDate = DateTimeUtils.dateStrToEpochSecond(String.valueOf(endDate), BaseConstant.DATE_FORMAT_YYYYMMDD, propertyDTO.getTimezone());

            return depCategoryHoursStatisticsService.getHoursStatisticsDaily(propertyDTO,
                    new SvaHoursStatisticsQuery(fromDate, toDate, departmentCode));
        }
    }