# GmwrWeeksServiceImpl.java

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

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.CommonErrorI18nConstant;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.exception.ForbiddenException;
    import cloud.wconnect.commonlib.pojo.dto.ListPagedDTO;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.UpdateLogUtil;
    import cloud.wconnect.commonlib.util.YearMonthUtils;
    import cloud.wconnect.workperformance.cons.gmwr.GmwrStatusEnum;
    import cloud.wconnect.workperformance.entity.gmwr.GmwrWeeks;
    import cloud.wconnect.workperformance.mapper.gmwr.GmwrWeeksMapper;
    import cloud.wconnect.workperformance.pojo.dto.gmwr.GmwrWeeksDTO;
    import cloud.wconnect.workperformance.pojo.dto.gmwr.valuedetail.GmwrBasicIntegerValueDetailDTO;
    import cloud.wconnect.workperformance.pojo.dto.gmwr.valuedetail.GmwrBasicValueDetailDTO;
    import cloud.wconnect.workperformance.pojo.query.gmwr.GmwrWeeksQuery;
    import cloud.wconnect.workperformance.service.gmwr.IGmwrWeeksService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import jakarta.annotation.Nullable;
    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.text.MessageFormat;
    import java.time.LocalDate;
    import java.util.Objects;

    /**
     * <p>
     * GM Weekly Report Weeks 服务实现类
     * </p>
     *
     * @author zc
     * @since 2024-10-12
     */
    @Service
    @DS("work_performance")
    public class GmwrWeeksServiceImpl extends ServiceImpl<GmwrWeeksMapper, GmwrWeeks> implements IGmwrWeeksService {
        @Resource
        private UpdateLogUtil updateLogUtil;
        @Resource
        private BeanMapper beanMapper;

        /**
         * 编辑 BigDecimal 数值
         *
         * @param originValueDTO 原始值
         * @param value          值
         * @param operatorId     操作人 id
         * @param nowTimestamp   当前时间戳
         * @author zc
         * @date 2025/5/16
         */
        @Override
        public void editValue(GmwrBasicValueDetailDTO originValueDTO, BigDecimal value, int operatorId, long nowTimestamp) {
            if (Objects.isNull(originValueDTO.getValue())) {
                if (Objects.isNull(value)) {
                    return;
                }
            } else {
                if (Objects.nonNull(value)) {
                    if (originValueDTO.getValue().compareTo(value) == 0) {
                        return;
                    }
                }
            }
            originValueDTO.setValue(value);
            originValueDTO.setUpdatedBy(operatorId);
            originValueDTO.setUpdatedTime(nowTimestamp);
        }

        /**
         * 编辑 Integer 数值
         *
         * @param originValueDTO 原始值
         * @param value          值
         * @param operatorId     操作人 id
         * @param nowTimestamp   当前时间戳
         * @author zc
         * @date 2025/5/16
         */
        @Override
        public void editValue(GmwrBasicIntegerValueDetailDTO originValueDTO, Integer value, int operatorId, long nowTimestamp) {
            if (Objects.isNull(originValueDTO.getValue())) {
                if (Objects.isNull(value)) {
                    return;
                }
            } else {
                if (Objects.nonNull(value)) {
                    if (originValueDTO.getValue().compareTo(value) == 0) {
                        return;
                    }
                }
            }
            originValueDTO.setValue(value);
            originValueDTO.setUpdatedBy(operatorId);
            originValueDTO.setUpdatedTime(nowTimestamp);
        }

        /**
         * 计算 Chg Percent
         *
         * @param value1       计算因子1
         * @param value2       计算因子2
         * @param roundingMode 舍入模式
         * @return Chg Percent
         * @author zc
         * @date 2024/10/15
         */
        @Override
        public BigDecimal calculateChg(BigDecimal value1, BigDecimal value2, RoundingMode roundingMode) {
            if (Objects.isNull(value1) || Objects.isNull(value2) || value2.compareTo(BigDecimal.ZERO) == 0) {
                return null;
            }
            return value1.divide(value2, BaseConstant.DATA_PRECISION + 2, roundingMode)
                    .subtract(new BigDecimal("1")).multiply(new BigDecimal("100"));
        }

        /**
         * 周报数据列表
         *
         * @param propertyId 资产 id
         * @param query      查询条件
         * @return GmwrWeeksDTO 集合
         * @author zc
         * @date 2024/10/15
         */
        @Override
        public ListPagedDTO<GmwrWeeksDTO> list(int propertyId, GmwrWeeksQuery query) {
            LambdaQueryWrapper<GmwrWeeks> queryWrapper = new LambdaQueryWrapper<GmwrWeeks>()
                    .eq(GmwrWeeks::getPropertyId, propertyId)
                    .in(CollectionUtils.isNotEmpty(query.getStatus()), GmwrWeeks::getStatus, query.getStatus())
                    .orderByDesc(GmwrWeeks::getWeek);
            if (Objects.nonNull(query.getStartMonth())) {
                long startDate = Long.parseLong(DateTimeUtils.localDateToStr(YearMonthUtils.getYearMonth(query.getStartMonth().toString())
                        .atDay(1), BaseConstant.DATE_FORMAT_YYYYMMDD));
                queryWrapper.ge(GmwrWeeks::getWeek, startDate);
            }
            if (Objects.nonNull(query.getEndMonth())) {
                long endDate = Long.parseLong(DateTimeUtils.localDateToStr(YearMonthUtils.getYearMonth(query.getEndMonth().toString())
                        .atEndOfMonth(), BaseConstant.DATE_FORMAT_YYYYMMDD));
                queryWrapper.le(GmwrWeeks::getWeek, endDate);
            }
            Page<GmwrWeeks> page = page(new Page<>(query.getPage(), query.getSize()), queryWrapper);
            return new ListPagedDTO<>(page.getTotal(), beanMapper.mapList(page.getRecords(), GmwrWeeksDTO.class, (entity, dto) -> {
                LocalDate localDate = DateTimeUtils.strToLocalDate(entity.getWeek().toString(), BaseConstant.DATE_FORMAT_YYYYMMDD);
                dto.setIndexOfMonth(DateTimeUtils.getWeekIndexOfMonth(localDate));
            }));
        }

        /**
         * 根据日期获取数据
         *
         * @param propertyId 资产 id
         * @param date       日期(yyyyMMdd)
         * @return GmwrWeeks
         * @author zc
         * @date 2025/2/28
         */
        @Override
        public GmwrWeeks getByDate(int propertyId, long date) {
            return getOne(new LambdaQueryWrapper<GmwrWeeks>()
                    .eq(GmwrWeeks::getWeek, date)
                    .eq(GmwrWeeks::getPropertyId, propertyId));
        }

        /**
         * 根据日期、状态获取数据
         *
         * @param propertyId    资产 id
         * @param weekStartDate 日期(yyyyMMdd)
         * @param status        状态 1:draft-草稿 2:complete-完成
         * @return GmwrWeeks
         * @author zc
         * @date 2025/1/23
         */
        @Override
        public GmwrWeeks getByDateAndStatus(int propertyId, long weekStartDate, @Nullable Integer status) {
            return getOne(new LambdaQueryWrapper<GmwrWeeks>()
                    .eq(GmwrWeeks::getWeek, weekStartDate)
                    .eq(GmwrWeeks::getPropertyId, propertyId)
                    .eq(Objects.nonNull(status), GmwrWeeks::getStatus, status));
        }

        /**
         * 检查是否存在
         *
         * @param id 周报 id
         * @return GmwrWeeks
         * @author zc
         * @date 2024/10/15
         */
        @Override
        public GmwrWeeks checkExist(int id) {
            GmwrWeeks gmwrWeeks = getById(id);
            if (Objects.isNull(gmwrWeeks)) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_FOUND,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "The gmwrWeeks is not found; id: " + id);
            }
            return gmwrWeeks;
        }

        /**
         * 校验归属
         *
         * @param propertyId 资产 id
         * @param gmwrWeeks  周报数据
         * @author zc
         * @date 2024/10/15
         */
        @Override
        public void checkBelong(int propertyId, GmwrWeeks gmwrWeeks) {
            if (!gmwrWeeks.getPropertyId().equals(propertyId)) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        MessageFormat.format("The gmwrWeeks does not belong to this property; propertyId:{0}; gmwrWeeksId:{1}",
                                propertyId, gmwrWeeks.getId()));
            }
        }

        /**
         * 变更状态
         *
         * @param gmwrWeeks    周报数据
         * @param operatorId   登录用户 id
         * @param changeStatus 变更状态
         * @author zc
         * @date 2024/10/15
         */
        @Override
        public void changeStatus(GmwrWeeks gmwrWeeks, int operatorId, int changeStatus) {
            update(new LambdaUpdateWrapper<GmwrWeeks>()
                    .eq(GmwrWeeks::getId, gmwrWeeks.getId())
                    .set(GmwrWeeks::getStatus, changeStatus)
                    .set(GmwrWeeks::getUpdateLog, updateLogUtil.append(gmwrWeeks.getUpdateLog(), operatorId)));
        }

        /**
         * 保存主数据
         *
         * @param propertyDTO   资产
         * @param weekStartDate 日期
         * @return GmwrWeeks
         * @author zc
         * @date 2024/10/16
         */
        @Override
        public GmwrWeeks save(PropertyDTO propertyDTO, LocalDate weekStartDate) {
            long date = Long.parseLong(DateTimeUtils.localDateToStr(weekStartDate, BaseConstant.DATE_FORMAT_YYYYMMDD));
            GmwrWeeks gmwrWeeks = getByDate(propertyDTO.getId(), date);
            if (Objects.isNull(gmwrWeeks)) {
                gmwrWeeks = new GmwrWeeks();
                gmwrWeeks.setPropertyId(propertyDTO.getId());
                gmwrWeeks.setWeek(date);
                gmwrWeeks.setStatus(GmwrStatusEnum.DRAFT.getStatus());
                gmwrWeeks.setUpdateLog("[]");

                save(gmwrWeeks);
            }
            return gmwrWeeks;
        }
    }