# SalesKpiFirstDayLogServiceImpl.java

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

    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.workperformance.entity.saleskpi.SalesKpiFirstDayLog;
    import cloud.wconnect.workperformance.mapper.saleskpi.SalesKpiFirstDayLogMapper;
    import cloud.wconnect.workperformance.pojo.dto.common.FirstDayDTO;
    import cloud.wconnect.workperformance.service.saleskpi.ISalesKpiFirstDayLogService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Service;

    import java.time.ZoneId;
    import java.time.ZonedDateTime;
    import java.time.temporal.ChronoField;
    import java.util.List;
    import java.util.Objects;

    /**
     * <p>
     * Sales KPI 周起始日log 服务实现类
     * </p>
     *
     * @author zc
     * @since 2023-09-14
     */
    @Service
    @DS("work_performance")
    public class SalesKpiFirstDayLogServiceImpl extends ServiceImpl<SalesKpiFirstDayLogMapper, SalesKpiFirstDayLog> implements ISalesKpiFirstDayLogService {

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

        /**
         * 获取周起始日
         *
         * @param propertyId 资产 id
         * @return firstDayOfWeek
         * @author zc
         * @date 2023/9/8
         */
        @Override
        public int getFirstDay(int propertyId) {
            SalesKpiFirstDayLog salesKpiFirstDay = getSalesKpiFirstDay(propertyId);
            return Objects.nonNull(salesKpiFirstDay) ? salesKpiFirstDay.getFirstDay() : defaultFirstDayOfWeek;
        }

        /**
         * 获取周起始日配置数据
         *
         * @param propertyId 资产 id
         * @return SalesKpiFirstDayLog
         * @author zc
         * @date 2023/9/8
         */
        private SalesKpiFirstDayLog getSalesKpiFirstDay(int propertyId) {
            return getOne(new QueryWrapper<SalesKpiFirstDayLog>().lambda()
                    .eq(SalesKpiFirstDayLog::getPropertyId, propertyId)
                    .orderByDesc(SalesKpiFirstDayLog::getCreateTime, SalesKpiFirstDayLog::getId)
                    .last("limit 1"));
        }

        /**
         * 保存周起始日
         *
         * @param propertyId  资产 id
         * @param userId      用户 id
         * @param firstDayDTO 周起始日
         * @author zc
         * @date 2023/9/8
         */
        @Override
        public void saveFirstDay(int propertyId, int userId, FirstDayDTO firstDayDTO) {
            save(SalesKpiFirstDayLog.builder()
                    .propertyId(propertyId)
                    .firstDay(firstDayDTO.getFirstDay())
                    .createBy(userId)
                    .createTime(DateTimeUtils.nowTimestamp())
                    .build());
        }

        /**
         * 获取资产配置的最新的周起始日数据
         *
         * @return SalesKpiFirstDayLog 集合
         * @author zc
         * @date 2023/9/14
         */
        @Override
        public List<SalesKpiFirstDayLog> getPropertyId2FirstDay() {
            return baseMapper.listMaxDateFirstDay();
        }

        /**
         * 转换为 Weekly 所在周的周起始日
         *
         * @param propertyId 资产 id
         * @param timezone   时区
         * @param weekly     周（yyyyMMdd）
         * @return 周起始日
         * @author zc
         * @date 2023/9/15
         */
        @Override
        public long conversionToFirstDayOfWeek(int propertyId, String timezone, long weekly) {
            ZonedDateTime targetWeeklyZonedDate = DateTimeUtils.strToLocalDate(String.valueOf(weekly), BaseConstant.DATE_FORMAT_YYYYMMDD)
                    .atStartOfDay(ZoneId.of(timezone));
            SalesKpiFirstDayLog salesKpiFirstDayLog = getOne(new QueryWrapper<SalesKpiFirstDayLog>().lambda()
                    .eq(SalesKpiFirstDayLog::getPropertyId, propertyId)
                    .le(SalesKpiFirstDayLog::getCreateTime, targetWeeklyZonedDate.toEpochSecond())
                    .orderByDesc(SalesKpiFirstDayLog::getCreateTime)
                    .last("limit 1"));

            int firstDayOfWeek = Objects.nonNull(salesKpiFirstDayLog) ? salesKpiFirstDayLog.getFirstDay() : defaultFirstDayOfWeek;
            ZonedDateTime targetFirstDayOfWeek = (targetWeeklyZonedDate.getDayOfWeek().getValue() >= firstDayOfWeek) ?
                    targetWeeklyZonedDate.with(ChronoField.DAY_OF_WEEK, firstDayOfWeek) :
                    targetWeeklyZonedDate.minusWeeks(1).with(ChronoField.DAY_OF_WEEK, firstDayOfWeek);
            return DateTimeUtils.parseToLong(targetFirstDayOfWeek, BaseConstant.DATE_FORMAT_YYYYMMDD);
        }

    }